From cfc55d31f4aa765e270e1ff0052e75b1326fc5f8 Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Wed, 22 Jul 2020 01:51:34 -0400 Subject: [PATCH 01/10] Updated latest version of the 0.16 spec --- Directory.Build.targets | 4 +- sample/SampleServer/Program.cs | 4 +- ...nticTokens.cs => SemanticTokensHandler.cs} | 20 +- src/Client/LanguageClient.cs | 6 +- src/Client/LanguageClientOptions.cs | 2 +- src/Client/LanguageClientOptionsExtensions.cs | 4 +- .../Capabilities/CallHierarchyCapability.cs | 16 ++ .../Capabilities/CompletionItemCapability.cs | 26 ++- ...ability.cs => SemanticTokensCapability.cs} | 25 ++- .../SemanticTokensCapabilityRequestFull.cs | 18 ++ .../SemanticTokensCapabilityRequestRange.cs | 10 + .../SemanticTokensCapabilityRequests.cs | 22 ++ .../SignatureInformationCapability.cs | 10 +- ...y.cs => TextDocumentClientCapabilities.cs} | 0 src/Protocol/Client/ILogTraceHandler.cs | 19 ++ ...dler.cs => ISemanticTokensDeltaHandler.cs} | 84 ++++---- .../Proposals/SemanticTokensDocument.cs | 12 +- src/Protocol/GeneralNames.cs | 2 + .../Models/ITextDocumentSyncOptions.cs | 2 +- src/Protocol/Models/InitializeParams.cs | 2 +- src/Protocol/Models/LogTraceParams.cs | 21 ++ .../Proposals/ISemanticTokensOptions.cs | 5 +- .../Models/Proposals/SemanticTokenFormat.cs | 64 ++++++ .../Proposals/SemanticTokenModifiers.cs | 3 + .../Models/Proposals/SemanticTokenTypes.cs | 4 +- .../Models/Proposals/SemanticTokens.cs | 2 +- ...cTokensEdits.cs => SemanticTokensDelta.cs} | 2 +- ...Params.cs => SemanticTokensDeltaParams.cs} | 6 +- ...cs => SemanticTokensDeltaPartialResult.cs} | 8 +- .../SemanticTokensDocumentProviderOptions.cs | 18 -- .../Models/Proposals/SemanticTokensEdit.cs | 2 + .../Proposals/SemanticTokensFullOrDelta.cs | 36 ++++ .../SemanticTokensFullOrDeltaPartialResult.cs | 38 ++++ .../Models/Proposals/SemanticTokensOptions.cs | 29 ++- .../SemanticTokensOrSemanticTokensEdits.cs | 36 ---- .../Models/Proposals/SemanticTokensParams.cs | 2 +- .../Proposals/SemanticTokensPartialResult.cs | 8 - ...esultOrSemanticTokensEditsPartialResult.cs | 40 ---- .../SemanticTokensRegistrationOptions.cs | 15 +- src/Protocol/Models/SetTraceParams.cs | 14 ++ src/Protocol/Models/SignatureInformation.cs | 11 + .../{InitializeTrace.cs => TraceValue.cs} | 2 +- .../SemanticTokensFullOrDeltaConverter.cs | 42 ++++ ...TokensFullOrDeltaPartialResultConverter.cs | 42 ++++ ...ticTokensOrSemanticTokensEditsConverter.cs | 42 ---- ...manticTokensEditsPartialResultConverter.cs | 42 ---- src/Protocol/Serialization/Serializer.cs | 4 +- .../Capabilities/TextDocumentSyncOptions.cs | 4 +- src/Protocol/Server/ISetTraceHandler.cs | 21 ++ src/Protocol/TextDocumentNames.cs | 4 +- src/Server/LanguageServer.cs | 2 +- test/Directory.Build.targets | 4 +- .../AutoNSubstitute/AutoSubstitute.cs | 202 ++++++++++-------- .../AutoNSubstitute/AutoTestBase.cs | 16 +- .../NSubstituteRegistrationHandler.cs | 66 ------ .../ClientCapabilitiesTests_$SimpleTest.json | 4 +- ...CompletionCapabilityTests_$SimpleTest.json | 4 +- ...letionItemCapabilityTests_$SimpleTest.json | 4 +- ...ntClientCapabilitiesTests_$SimpleTest.json | 4 +- test/Lsp.Tests/FoundationTests.cs | 3 +- .../Integration/DynamicRegistrationTests.cs | 10 +- .../Lsp.Tests/Models/InitializeParamsTests.cs | 2 +- .../InitializeParamsTests_$SimpleTest.json | 6 +- .../SignatureHelpTests_$SimpleTest.json | 2 +- test/Lsp.Tests/SemanticTokensDocumentTests.cs | 76 +++---- 65 files changed, 723 insertions(+), 537 deletions(-) rename sample/SampleServer/{SemanticTokens.cs => SemanticTokensHandler.cs} (80%) create mode 100644 src/Protocol/Client/Capabilities/CallHierarchyCapability.cs rename src/Protocol/Client/Capabilities/{CallHierarchyClientCapability.cs => SemanticTokensCapability.cs} (66%) create mode 100644 src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestFull.cs create mode 100644 src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestRange.cs create mode 100644 src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequests.cs rename src/Protocol/Client/Capabilities/{TextDocumentCapability.cs => TextDocumentClientCapabilities.cs} (100%) create mode 100644 src/Protocol/Client/ILogTraceHandler.cs rename src/Protocol/Document/Proposals/{ISemanticTokensEditsHandler.cs => ISemanticTokensDeltaHandler.cs} (73%) create mode 100644 src/Protocol/Models/LogTraceParams.cs create mode 100644 src/Protocol/Models/Proposals/SemanticTokenFormat.cs rename src/Protocol/Models/Proposals/{SemanticTokensEdits.cs => SemanticTokensDelta.cs} (96%) rename src/Protocol/Models/Proposals/{SemanticTokensEditsParams.cs => SemanticTokensDeltaParams.cs} (71%) rename src/Protocol/Models/Proposals/{SemanticTokensEditsPartialResult.cs => SemanticTokensDeltaPartialResult.cs} (65%) delete mode 100644 src/Protocol/Models/Proposals/SemanticTokensDocumentProviderOptions.cs create mode 100644 src/Protocol/Models/Proposals/SemanticTokensFullOrDelta.cs create mode 100644 src/Protocol/Models/Proposals/SemanticTokensFullOrDeltaPartialResult.cs delete mode 100644 src/Protocol/Models/Proposals/SemanticTokensOrSemanticTokensEdits.cs delete mode 100644 src/Protocol/Models/Proposals/SemanticTokensPartialResultOrSemanticTokensEditsPartialResult.cs create mode 100644 src/Protocol/Models/SetTraceParams.cs rename src/Protocol/Models/{InitializeTrace.cs => TraceValue.cs} (92%) create mode 100644 src/Protocol/Serialization/Converters/SemanticTokensFullOrDeltaConverter.cs create mode 100644 src/Protocol/Serialization/Converters/SemanticTokensFullOrDeltaPartialResultConverter.cs delete mode 100644 src/Protocol/Serialization/Converters/SemanticTokensOrSemanticTokensEditsConverter.cs delete mode 100644 src/Protocol/Serialization/Converters/SemanticTokensPartialResultOrSemanticTokensEditsPartialResultConverter.cs create mode 100644 src/Protocol/Server/ISetTraceHandler.cs delete mode 100644 test/JsonRpc.Tests/AutoNSubstitute/NSubstituteRegistrationHandler.cs diff --git a/Directory.Build.targets b/Directory.Build.targets index ad9b19cce..05e3aee37 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -26,8 +26,8 @@ - - + + diff --git a/sample/SampleServer/Program.cs b/sample/SampleServer/Program.cs index 0de769848..0226f4b71 100644 --- a/sample/SampleServer/Program.cs +++ b/sample/SampleServer/Program.cs @@ -37,8 +37,6 @@ static async Task MainAsync(string[] args) var server = await LanguageServer.From(options => options - .WithInput(Console.OpenStandardInput()) - .WithOutput(Console.OpenStandardOutput()) .ConfigureLogging(x => x .AddSerilog() .AddLanguageProtocolLogging() @@ -48,7 +46,7 @@ static async Task MainAsync(string[] args) .WithHandler() .WithHandler() .WithHandler() - .WithHandler() + .WithHandler() .WithServices(x => x.AddLogging(b => b.SetMinimumLevel(LogLevel.Trace))) .WithServices(services => { services.AddSingleton(provider => { diff --git a/sample/SampleServer/SemanticTokens.cs b/sample/SampleServer/SemanticTokensHandler.cs similarity index 80% rename from sample/SampleServer/SemanticTokens.cs rename to sample/SampleServer/SemanticTokensHandler.cs index b96ccad40..ac6dc121a 100644 --- a/sample/SampleServer/SemanticTokens.cs +++ b/sample/SampleServer/SemanticTokensHandler.cs @@ -7,6 +7,7 @@ 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; @@ -14,38 +15,37 @@ namespace SampleServer { #pragma warning disable 618 - public class SemanticTokens : SemanticTokensHandler + public class SemanticTokensHandler : SemanticTokensHandlerBase { private readonly ILogger _logger; - public SemanticTokens(ILogger logger) : base(new SemanticTokensRegistrationOptions() { + public SemanticTokensHandler(ILogger logger) : base(new SemanticTokensRegistrationOptions() { DocumentSelector = DocumentSelector.ForLanguage("csharp"), Legend = new SemanticTokensLegend(), - DocumentProvider = new Supports(true, - new SemanticTokensDocumentProviderOptions() { - Edits = true - }), - RangeProvider = true + Full = new SemanticTokensCapabilityRequestFull() { + Delta = true + }, + Range = true }) { _logger = logger; } - public override async Task Handle( + public override async Task Handle( SemanticTokensParams request, CancellationToken cancellationToken) { var result = await base.Handle(request, cancellationToken); return result; } - public override async Task Handle( + public override async Task Handle( SemanticTokensRangeParams request, CancellationToken cancellationToken) { var result = await base.Handle(request, cancellationToken); return result; } - public override async Task Handle(SemanticTokensEditsParams request, + public override async Task Handle(SemanticTokensDeltaParams request, CancellationToken cancellationToken) { var result = await base.Handle(request, cancellationToken); diff --git a/src/Client/LanguageClient.cs b/src/Client/LanguageClient.cs index 6a3fb6f94..c40da94bd 100644 --- a/src/Client/LanguageClient.cs +++ b/src/Client/LanguageClient.cs @@ -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; @@ -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(_ => @@ -220,7 +220,7 @@ internal LanguageClient(LanguageClientOptions options) : base(options) public async Task Initialize(CancellationToken token) { var @params = new InitializeParams { - Trace = _trace, + TraceValue = _traceValue, Capabilities = _clientCapabilities, ClientInfo = _clientInfo, RootUri = _rootUri, diff --git a/src/Client/LanguageClientOptions.cs b/src/Client/LanguageClientOptions.cs index 33db58c91..a73a31ff0 100644 --- a/src/Client/LanguageClientOptions.cs +++ b/src/Client/LanguageClientOptions.cs @@ -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; } diff --git a/src/Client/LanguageClientOptionsExtensions.cs b/src/Client/LanguageClientOptionsExtensions.cs index 024e7713f..006e532f0 100644 --- a/src/Client/LanguageClientOptionsExtensions.cs +++ b/src/Client/LanguageClientOptionsExtensions.cs @@ -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; } diff --git a/src/Protocol/Client/Capabilities/CallHierarchyCapability.cs b/src/Protocol/Client/Capabilities/CallHierarchyCapability.cs new file mode 100644 index 000000000..7e0204f13 --- /dev/null +++ b/src/Protocol/Client/Capabilities/CallHierarchyCapability.cs @@ -0,0 +1,16 @@ +using System; +using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities +{ + /// + /// Capabilities specific to the `textDocument/callHierarchy`. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + public class CallHierarchyCapability : DynamicCapability, ConnectedCapability, + ConnectedCapability, ConnectedCapability + { + } +} diff --git a/src/Protocol/Client/Capabilities/CompletionItemCapability.cs b/src/Protocol/Client/Capabilities/CompletionItemCapability.cs index c50c63762..5405d8419 100644 --- a/src/Protocol/Client/Capabilities/CompletionItemCapability.cs +++ b/src/Protocol/Client/Capabilities/CompletionItemCapability.cs @@ -30,14 +30,14 @@ public class CompletionItemCapability public Container DocumentationFormat { get; set; } /// - /// Client supports the deprecated property on a completion item. - /// + /// Client supports the deprecated property on a completion item. + /// [Optional] public bool DeprecatedSupport { get; set; } /// - /// Client supports the preselect property on a completion item. - /// + /// Client supports the preselect property on a completion item. + /// [Optional] public bool PreselectSupport { get; set; } @@ -51,5 +51,23 @@ public class CompletionItemCapability /// [Optional] public Supports TagSupport { get; set; } + + /// + /// 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 + /// + [Optional] + public bool InsertReplaceSupport { get; set; } + + /// + /// Client supports to resolve `additionalTextEdits` in the `completionItem/resolve` + /// request. So servers can postpone computing them. + /// + /// @since 3.16.0 - Proposed state + /// + [Optional] + public bool ResolveAdditionalTextEditsSupport { get; set; } } } diff --git a/src/Protocol/Client/Capabilities/CallHierarchyClientCapability.cs b/src/Protocol/Client/Capabilities/SemanticTokensCapability.cs similarity index 66% rename from src/Protocol/Client/Capabilities/CallHierarchyClientCapability.cs rename to src/Protocol/Client/Capabilities/SemanticTokensCapability.cs index be2c3489d..401e248bd 100644 --- a/src/Protocol/Client/Capabilities/CallHierarchyClientCapability.cs +++ b/src/Protocol/Client/Capabilities/SemanticTokensCapability.cs @@ -1,21 +1,10 @@ -using System; +using System; using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities { - /// - /// Capabilities specific to the `textDocument/callHierarchy`. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class CallHierarchyCapability : DynamicCapability, ConnectedCapability, - ConnectedCapability, ConnectedCapability - { - } - /// /// Capabilities specific to the `textDocument/semanticTokens` /// @@ -23,8 +12,13 @@ public class CallHierarchyCapability : DynamicCapability, ConnectedCapability [Obsolete(Constants.Proposal)] public class SemanticTokensCapability : DynamicCapability, ConnectedCapability, - ConnectedCapability, ConnectedCapability + ConnectedCapability, ConnectedCapability { + /// + /// Which requests the client supports and might send to the server. + /// + public SemanticTokensCapabilityRequests Requests { get; set; } + /// /// The token types that the client supports. /// @@ -34,5 +28,10 @@ public class SemanticTokensCapability : DynamicCapability, ConnectedCapability public Container TokenModifiers { get; set; } + + /// + /// The formats the clients supports. + /// + public Container Formats { get; set; } } } diff --git a/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestFull.cs b/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestFull.cs new file mode 100644 index 000000000..fbba5f343 --- /dev/null +++ b/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestFull.cs @@ -0,0 +1,18 @@ +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities +{ + /// + /// The client will send the `textDocument/semanticTokens/full` request if + /// the server provides a corresponding handler. + /// + public class SemanticTokensCapabilityRequestFull + { + /// + /// The client will send the `textDocument/semanticTokens/full/delta` request if + /// the server provides a corresponding handler. + /// + [Optional] + public bool Delta { get; set; } + } +} \ No newline at end of file diff --git a/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestRange.cs b/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestRange.cs new file mode 100644 index 000000000..25456bf4c --- /dev/null +++ b/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestRange.cs @@ -0,0 +1,10 @@ +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities +{ + /// + /// The client will send the `textDocument/semanticTokens/range` request if + /// the server provides a corresponding handler. + /// + public class SemanticTokensCapabilityRequestRange + { + } +} \ No newline at end of file diff --git a/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequests.cs b/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequests.cs new file mode 100644 index 000000000..dc97bae4b --- /dev/null +++ b/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequests.cs @@ -0,0 +1,22 @@ +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities +{ + public class SemanticTokensCapabilityRequests + { + /// + /// The client will send the `textDocument/semanticTokens/range` request if + /// the server provides a corresponding handler. + /// + [Optional] + public Supports Range { get; set; } + + /// + /// The client will send the `textDocument/semanticTokens/full` request if + /// the server provides a corresponding handler. + /// + [Optional] + public Supports Full { get; set; } + } +} diff --git a/src/Protocol/Client/Capabilities/SignatureInformationCapability.cs b/src/Protocol/Client/Capabilities/SignatureInformationCapability.cs index 210e9ac96..529f9a5ae 100644 --- a/src/Protocol/Client/Capabilities/SignatureInformationCapability.cs +++ b/src/Protocol/Client/Capabilities/SignatureInformationCapability.cs @@ -11,7 +11,15 @@ public class SignatureInformationCapability [Optional] public Container DocumentationFormat { get; set; } + [Optional] public SignatureParameterInformationCapability ParameterInformation { get; set; } + + /// + /// The client support the `activeParameter` property on `SignatureInformation` + /// literal. + /// + /// @since 3.16.0 - proposed state + /// [Optional] - public SignatureParameterInformationCapability ParameterInformation { get; set; } + public bool ActiveParameterSupport { get; set; } } } diff --git a/src/Protocol/Client/Capabilities/TextDocumentCapability.cs b/src/Protocol/Client/Capabilities/TextDocumentClientCapabilities.cs similarity index 100% rename from src/Protocol/Client/Capabilities/TextDocumentCapability.cs rename to src/Protocol/Client/Capabilities/TextDocumentClientCapabilities.cs diff --git a/src/Protocol/Client/ILogTraceHandler.cs b/src/Protocol/Client/ILogTraceHandler.cs new file mode 100644 index 000000000..5cbfcc928 --- /dev/null +++ b/src/Protocol/Client/ILogTraceHandler.cs @@ -0,0 +1,19 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client +{ + [Parallel, Method(GeneralNames.LogTrace, Direction.ServerToClient)] + [GenerateHandlerMethods, GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer))] + public interface ILogTraceHandler : IJsonRpcNotificationHandler { } + + public abstract class LogTraceHandler : ILogTraceHandler + { + public abstract Task Handle(LogTraceParams request, CancellationToken cancellationToken); + } +} diff --git a/src/Protocol/Document/Proposals/ISemanticTokensEditsHandler.cs b/src/Protocol/Document/Proposals/ISemanticTokensDeltaHandler.cs similarity index 73% rename from src/Protocol/Document/Proposals/ISemanticTokensEditsHandler.cs rename to src/Protocol/Document/Proposals/ISemanticTokensDeltaHandler.cs index e0c4e2ed5..18f8be8ad 100644 --- a/src/Protocol/Document/Proposals/ISemanticTokensEditsHandler.cs +++ b/src/Protocol/Document/Proposals/ISemanticTokensDeltaHandler.cs @@ -12,16 +12,16 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals { [Obsolete(Constants.Proposal)] - [Parallel, Method(TextDocumentNames.SemanticTokens, Direction.ClientToServer)] + [Parallel, Method(TextDocumentNames.SemanticTokensFull, Direction.ClientToServer)] public interface ISemanticTokensHandler : IJsonRpcRequestHandler, IRegistration, ICapability { } [Obsolete(Constants.Proposal)] - [Parallel, Method(TextDocumentNames.SemanticTokensEdits, Direction.ClientToServer)] - public interface ISemanticTokensEditsHandler : - IJsonRpcRequestHandler, + [Parallel, Method(TextDocumentNames.SemanticTokensFullDelta, Direction.ClientToServer)] + public interface ISemanticTokensDeltaHandler : + IJsonRpcRequestHandler, IRegistration, ICapability { } @@ -34,12 +34,12 @@ public interface ISemanticTokensRangeHandler : IJsonRpcRequestHandler Handle(SemanticTokensParams request, C return builder.Commit().GetSemanticTokens(); } - public virtual async Task Handle(SemanticTokensEditsParams request, CancellationToken cancellationToken) + public virtual async Task Handle(SemanticTokensDeltaParams request, CancellationToken cancellationToken) { var document = await GetSemanticTokensDocument(request, cancellationToken); var builder = document.Edit(request); @@ -87,18 +87,16 @@ public static ILanguageServerRegistry OnSemanticTokens(this ILanguageServerRegis SemanticTokensRegistrationOptions registrationOptions) { registrationOptions ??= new SemanticTokensRegistrationOptions() { - DocumentProvider = - new Supports(true, - new SemanticTokensDocumentProviderOptions() { }) + Full = new SemanticTokensCapabilityRequestFull() }; - registrationOptions.RangeProvider = true; - if (registrationOptions.DocumentProvider != null) + registrationOptions.Range ??= new SemanticTokensCapabilityRequestRange(); + if (registrationOptions?.Full?.IsValue == true) { - registrationOptions.DocumentProvider.Edits = true; + registrationOptions.Full.Value.Delta = true; } return registry.AddHandlers( - new DelegatingHandler(tokenize, getSemanticTokensDocument, registrationOptions)); + new DelegatingHandlerBase(tokenize, getSemanticTokensDocument, registrationOptions)); } public static ILanguageServerRegistry OnSemanticTokens(this ILanguageServerRegistry registry, @@ -106,18 +104,17 @@ public static ILanguageServerRegistry OnSemanticTokens(this ILanguageServerRegis Func> getSemanticTokensDocument, SemanticTokensRegistrationOptions registrationOptions) { - registrationOptions ??= new SemanticTokensRegistrationOptions(); - registrationOptions.DocumentProvider = - new Supports(true, - new SemanticTokensDocumentProviderOptions() { }); - registrationOptions.RangeProvider = true; - if (registrationOptions.DocumentProvider != null) + registrationOptions ??= new SemanticTokensRegistrationOptions() { + Full = new SemanticTokensCapabilityRequestFull() + }; + registrationOptions.Range ??= new SemanticTokensCapabilityRequestRange(); + if (registrationOptions?.Full?.IsValue == true) { - registrationOptions.DocumentProvider.Edits = true; + registrationOptions.Full.Value.Delta = true; } return registry.AddHandlers( - new DelegatingHandler( + new DelegatingHandlerBase( (a, t, c, ct) => tokenize(a, t, ct), (a, c, ct) => getSemanticTokensDocument(a, ct), registrationOptions)); @@ -128,31 +125,30 @@ public static ILanguageServerRegistry OnSemanticTokens(this ILanguageServerRegis Func> getSemanticTokensDocument, SemanticTokensRegistrationOptions registrationOptions) { - registrationOptions ??= new SemanticTokensRegistrationOptions(); - registrationOptions.DocumentProvider = - new Supports(true, - new SemanticTokensDocumentProviderOptions() { }); - registrationOptions.RangeProvider = true; - if (registrationOptions.DocumentProvider != null) + registrationOptions ??= new SemanticTokensRegistrationOptions() { + Full = new SemanticTokensCapabilityRequestFull() + }; + registrationOptions.Range ??= new SemanticTokensCapabilityRequestRange(); + if (registrationOptions?.Full?.IsValue == true) { - registrationOptions.DocumentProvider.Edits = true; + registrationOptions.Full.Value.Delta = true; } return registry.AddHandlers( - new DelegatingHandler( + new DelegatingHandlerBase( (a, t, c, ct) => tokenize(a, t), (a, c, ct) => getSemanticTokensDocument(a), registrationOptions)); } - class DelegatingHandler : SemanticTokensHandler + class DelegatingHandlerBase : SemanticTokensHandlerBase { private readonly Func _tokenize; private readonly Func> _getSemanticTokensDocument; private SemanticTokensCapability _capability; - public DelegatingHandler( + public DelegatingHandlerBase( Func tokenize, Func> getSemanticTokensDocument, SemanticTokensRegistrationOptions registrationOptions @@ -162,7 +158,7 @@ SemanticTokensRegistrationOptions registrationOptions _getSemanticTokensDocument = getSemanticTokensDocument; } - public DelegatingHandler( + public DelegatingHandlerBase( Func tokenize, Func> getSemanticTokensDocument, SemanticTokensRegistrationOptions registrationOptions @@ -194,27 +190,27 @@ public static IRequestProgressObservable RequestSemanticTokensEdits( - this ITextDocumentLanguageClient mediator, SemanticTokensEditsParams @params, CancellationToken cancellationToken = default) + public static IRequestProgressObservable RequestSemanticTokensDelta( + this ITextDocumentLanguageClient mediator, SemanticTokensDeltaParams @params, CancellationToken cancellationToken = default) { return mediator.ProgressManager.MonitorUntil(@params, (partial, result) => { - if (partial.IsSemanticTokensPartialResult) + if (partial.IsDelta) { - return new SemanticTokensOrSemanticTokensEdits(new SemanticTokens() { - Data = partial.SemanticTokensPartialResult.Data, - ResultId = result.SemanticTokens?.ResultId ?? result.SemanticTokensEdits?.ResultId + return new SemanticTokensFullOrDelta(new SemanticTokensDelta() { + Edits = partial.Delta.Edits, + ResultId = result.Delta?.ResultId ?? result.Full?.ResultId }); } - if (partial.IsSemanticTokensEditsPartialResult) + if (partial.IsFull) { - return new SemanticTokensOrSemanticTokensEdits(new SemanticTokensEdits() { - Edits = partial.SemanticTokensEditsPartialResult.Edits, - ResultId = result.SemanticTokensEdits?.ResultId ?? result.SemanticTokens?.ResultId + return new SemanticTokensFullOrDelta(new SemanticTokens() { + Data = partial.Full.Data, + ResultId = result.Full?.ResultId ?? result.Delta?.ResultId }); } - return new SemanticTokensOrSemanticTokensEdits(new SemanticTokens()); + return new SemanticTokensFullOrDelta(new SemanticTokens()); }, cancellationToken); } diff --git a/src/Protocol/Document/Proposals/SemanticTokensDocument.cs b/src/Protocol/Document/Proposals/SemanticTokensDocument.cs index def762617..8bc5981ac 100644 --- a/src/Protocol/Document/Proposals/SemanticTokensDocument.cs +++ b/src/Protocol/Document/Proposals/SemanticTokensDocument.cs @@ -43,7 +43,7 @@ public SemanticTokensBuilder Create() return new SemanticTokensBuilder(this, _legend); } - public SemanticTokensBuilder Edit(SemanticTokensEditsParams @params) + public SemanticTokensBuilder Edit(SemanticTokensDeltaParams @params) { if (@params.PreviousResultId == Id) { @@ -151,7 +151,7 @@ public SemanticTokens GetSemanticTokens(Range range) }; } - public SemanticTokensOrSemanticTokensEdits GetSemanticTokensEdits() + public SemanticTokensFullOrDelta GetSemanticTokensEdits() { if (!_prevData.HasValue) return GetSemanticTokens(); @@ -176,7 +176,7 @@ public SemanticTokensOrSemanticTokensEdits GetSemanticTokensEdits() } var newData = ImmutableArray.Create(_data, startIndex, dataLength - endIndex - startIndex); - var result = new SemanticTokensEdits { + var result = new SemanticTokensDelta { ResultId = Id, Edits = new[] { new SemanticTokensEdit { @@ -191,7 +191,7 @@ public SemanticTokensOrSemanticTokensEdits GetSemanticTokensEdits() if (startIndex < dataLength) { - return new SemanticTokensEdits { + return new SemanticTokensDelta { ResultId = Id, Edits = new[] { new SemanticTokensEdit { Start = startIndex, @@ -204,7 +204,7 @@ public SemanticTokensOrSemanticTokensEdits GetSemanticTokensEdits() if (startIndex < prevDataLength) { - return new SemanticTokensEdits { + return new SemanticTokensDelta { ResultId = Id, Edits = new[] { new SemanticTokensEdit { @@ -215,7 +215,7 @@ public SemanticTokensOrSemanticTokensEdits GetSemanticTokensEdits() }; } - return new SemanticTokensEdits { + return new SemanticTokensDelta { ResultId = Id, Edits = Array.Empty() }; } diff --git a/src/Protocol/GeneralNames.cs b/src/Protocol/GeneralNames.cs index 2eda4d1b4..223f5f9be 100644 --- a/src/Protocol/GeneralNames.cs +++ b/src/Protocol/GeneralNames.cs @@ -3,6 +3,8 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol public static class GeneralNames { public const string Progress = "$/progress"; + public const string LogTrace = "$/logTrace"; + public const string SetTrace = "$/setTrace"; public const string Exit = "exit"; public const string Initialized = "initialized"; public const string Initialize = "initialize"; diff --git a/src/Protocol/Models/ITextDocumentSyncOptions.cs b/src/Protocol/Models/ITextDocumentSyncOptions.cs index 46fefa0b7..24a48318a 100644 --- a/src/Protocol/Models/ITextDocumentSyncOptions.cs +++ b/src/Protocol/Models/ITextDocumentSyncOptions.cs @@ -8,6 +8,6 @@ public interface ITextDocumentSyncOptions TextDocumentSyncKind Change { get; set; } bool WillSave { get; set; } bool WillSaveWaitUntil { get; set; } - SaveOptions Save { get; set; } + BooleanOr Save { get; set; } } } diff --git a/src/Protocol/Models/InitializeParams.cs b/src/Protocol/Models/InitializeParams.cs index 9f0c595d1..1a8009ec9 100644 --- a/src/Protocol/Models/InitializeParams.cs +++ b/src/Protocol/Models/InitializeParams.cs @@ -57,7 +57,7 @@ public string RootPath /// The initial trace setting. If omitted trace is disabled ('off'). /// [Optional] - public InitializeTrace Trace { get; set; } = InitializeTrace.Off; + public TraceValue TraceValue { get; set; } = TraceValue.Off; /// /// The workspace folders configured in the client when the server starts. diff --git a/src/Protocol/Models/LogTraceParams.cs b/src/Protocol/Models/LogTraceParams.cs new file mode 100644 index 000000000..fcc2b4055 --- /dev/null +++ b/src/Protocol/Models/LogTraceParams.cs @@ -0,0 +1,21 @@ +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + [Method(GeneralNames.LogTrace, Direction.ServerToClient)] + public class LogTraceParams : IRequest + { + /// + /// The message to be logged. + /// + public string Message { get; set; } + + /// + /// Additional information that can be computed if the `trace` configuration is set to `'verbose'` + /// + [Optional] + public string Verbose { get; set; } + } +} diff --git a/src/Protocol/Models/Proposals/ISemanticTokensOptions.cs b/src/Protocol/Models/Proposals/ISemanticTokensOptions.cs index a7a790ca0..726c96dcf 100644 --- a/src/Protocol/Models/Proposals/ISemanticTokensOptions.cs +++ b/src/Protocol/Models/Proposals/ISemanticTokensOptions.cs @@ -1,4 +1,5 @@ using System; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals @@ -22,12 +23,12 @@ public interface ISemanticTokensOptions : IWorkDoneProgressOptions /// [Optional] - public bool RangeProvider { get; set; } + public BooleanOr Range { get; set; } /// /// Server supports providing semantic tokens for a full document. /// [Optional] - public SemanticTokensDocumentProviderOptions DocumentProvider { get; set; } + public BooleanOr Full { get; set; } } } diff --git a/src/Protocol/Models/Proposals/SemanticTokenFormat.cs b/src/Protocol/Models/Proposals/SemanticTokenFormat.cs new file mode 100644 index 000000000..4a6045499 --- /dev/null +++ b/src/Protocol/Models/Proposals/SemanticTokenFormat.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals +{ + /// + /// The protocol defines an additional token format capability to allow future extensions of the format. + /// The only format that is currently specified is `relative` expressing that the tokens are described using relative positions. + /// + /// @since 3.16.0 + /// + [JsonConverter(typeof(EnumLikeStringConverter))] + [Obsolete(Constants.Proposal)] + [DebuggerDisplay("{_value}")] + public readonly struct SemanticTokenFormat : IEquatable, IEnumLikeString + { + private static readonly Lazy> _defaults = + new Lazy>( + () => { + return typeof(SemanticTokenFormat) + .GetFields(BindingFlags.Static | BindingFlags.Public) + .Select(z => z.GetValue(null)) + .Cast() + .ToArray(); + }); + + public static IEnumerable Defaults => _defaults.Value; + + public static readonly SemanticTokenFormat Relative = new SemanticTokenFormat("relative"); + + private readonly string _value; + + public SemanticTokenFormat(string modifier) + { + _value = modifier; + } + + public static implicit operator SemanticTokenFormat(string kind) + { + return new SemanticTokenFormat(kind); + } + + public static implicit operator string(SemanticTokenFormat kind) + { + return kind._value; + } + + public override string ToString() => _value; + public bool Equals(SemanticTokenFormat other) => _value == other._value; + + public override bool Equals(object obj) => obj is SemanticTokenFormat other && Equals(other); + + public override int GetHashCode() => (_value != null ? _value.GetHashCode() : 0); + + public static bool operator ==(SemanticTokenFormat left, SemanticTokenFormat right) => left.Equals(right); + + public static bool operator !=(SemanticTokenFormat left, SemanticTokenFormat right) => !left.Equals(right); + } +} diff --git a/src/Protocol/Models/Proposals/SemanticTokenModifiers.cs b/src/Protocol/Models/Proposals/SemanticTokenModifiers.cs index 893f17894..12b15afa3 100644 --- a/src/Protocol/Models/Proposals/SemanticTokenModifiers.cs +++ b/src/Protocol/Models/Proposals/SemanticTokenModifiers.cs @@ -36,9 +36,12 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals public static readonly SemanticTokenModifier Declaration = new SemanticTokenModifier("declaration"); public static readonly SemanticTokenModifier Definition = new SemanticTokenModifier("definition"); public static readonly SemanticTokenModifier Static = new SemanticTokenModifier("static"); + public static readonly SemanticTokenModifier Async = new SemanticTokenModifier("async"); public static readonly SemanticTokenModifier Abstract = new SemanticTokenModifier("abstract"); public static readonly SemanticTokenModifier Deprecated = new SemanticTokenModifier("deprecated"); public static readonly SemanticTokenModifier Readonly = new SemanticTokenModifier("readonly"); + public static readonly SemanticTokenModifier Modification = new SemanticTokenModifier("modification"); + public static readonly SemanticTokenModifier DefaultLibrary = new SemanticTokenModifier("defaultLibrary"); private readonly string _value; diff --git a/src/Protocol/Models/Proposals/SemanticTokenTypes.cs b/src/Protocol/Models/Proposals/SemanticTokenTypes.cs index cc916886a..2b19f7714 100644 --- a/src/Protocol/Models/Proposals/SemanticTokenTypes.cs +++ b/src/Protocol/Models/Proposals/SemanticTokenTypes.cs @@ -32,7 +32,6 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals public static IEnumerable Defaults => _defaults.Value; - public static readonly SemanticTokenType Documentation = new SemanticTokenType("documentation"); public static readonly SemanticTokenType Comment = new SemanticTokenType("comment"); public static readonly SemanticTokenType Keyword = new SemanticTokenType("keyword"); public static readonly SemanticTokenType String = new SemanticTokenType("string"); @@ -53,6 +52,9 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals public static readonly SemanticTokenType Variable = new SemanticTokenType("variable"); public static readonly SemanticTokenType Parameter = new SemanticTokenType("parameter"); public static readonly SemanticTokenType Label = new SemanticTokenType("label"); + public static readonly SemanticTokenType Modifier = new SemanticTokenType("modifier"); + public static readonly SemanticTokenType Event = new SemanticTokenType("event"); + public static readonly SemanticTokenType EnumMember = new SemanticTokenType("enumMember"); private readonly string _value; diff --git a/src/Protocol/Models/Proposals/SemanticTokens.cs b/src/Protocol/Models/Proposals/SemanticTokens.cs index eebcc020d..61d1413b7 100644 --- a/src/Protocol/Models/Proposals/SemanticTokens.cs +++ b/src/Protocol/Models/Proposals/SemanticTokens.cs @@ -24,6 +24,6 @@ public class SemanticTokens /// structured pls see /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 /// - public ImmutableArray Data { get; set; } + public ImmutableArray Data { get; set; } = ImmutableArray.Empty; } } diff --git a/src/Protocol/Models/Proposals/SemanticTokensEdits.cs b/src/Protocol/Models/Proposals/SemanticTokensDelta.cs similarity index 96% rename from src/Protocol/Models/Proposals/SemanticTokensEdits.cs rename to src/Protocol/Models/Proposals/SemanticTokensDelta.cs index 129d2cd31..b6bda34ac 100644 --- a/src/Protocol/Models/Proposals/SemanticTokensEdits.cs +++ b/src/Protocol/Models/Proposals/SemanticTokensDelta.cs @@ -7,7 +7,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals /// @since 3.16.0 /// [Obsolete(Constants.Proposal)] - public class SemanticTokensEdits + public class SemanticTokensDelta { /// /// An optional result id. If provided and clients support delta updating diff --git a/src/Protocol/Models/Proposals/SemanticTokensEditsParams.cs b/src/Protocol/Models/Proposals/SemanticTokensDeltaParams.cs similarity index 71% rename from src/Protocol/Models/Proposals/SemanticTokensEditsParams.cs rename to src/Protocol/Models/Proposals/SemanticTokensDeltaParams.cs index 7985a2ef9..fa809cdf5 100644 --- a/src/Protocol/Models/Proposals/SemanticTokensEditsParams.cs +++ b/src/Protocol/Models/Proposals/SemanticTokensDeltaParams.cs @@ -7,9 +7,9 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals /// @since 3.16.0 /// [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.SemanticTokensEdits, Direction.ClientToServer)] - public class SemanticTokensEditsParams : IWorkDoneProgressParams, ITextDocumentIdentifierParams, - IPartialItemRequest + [Method(TextDocumentNames.SemanticTokensFullDelta, Direction.ClientToServer)] + public class SemanticTokensDeltaParams : IWorkDoneProgressParams, ITextDocumentIdentifierParams, + IPartialItemRequest { /// /// The text document. diff --git a/src/Protocol/Models/Proposals/SemanticTokensEditsPartialResult.cs b/src/Protocol/Models/Proposals/SemanticTokensDeltaPartialResult.cs similarity index 65% rename from src/Protocol/Models/Proposals/SemanticTokensEditsPartialResult.cs rename to src/Protocol/Models/Proposals/SemanticTokensDeltaPartialResult.cs index 39bea87e4..5a678d07c 100644 --- a/src/Protocol/Models/Proposals/SemanticTokensEditsPartialResult.cs +++ b/src/Protocol/Models/Proposals/SemanticTokensDeltaPartialResult.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Immutable; namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals { @@ -6,11 +7,12 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals /// @since 3.16.0 /// [Obsolete(Constants.Proposal)] - public class SemanticTokensEditsPartialResult + public class SemanticTokensDeltaPartialResult { /// - /// For a detailed description how these edits are structured pls see - /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L131 + /// The actual tokens. For a detailed description about how the data is + /// structured pls see + /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 /// public Container Edits { get; set; } } diff --git a/src/Protocol/Models/Proposals/SemanticTokensDocumentProviderOptions.cs b/src/Protocol/Models/Proposals/SemanticTokensDocumentProviderOptions.cs deleted file mode 100644 index 994308dc3..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensDocumentProviderOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// Server supports providing semantic tokens for a full document. - /// - [Obsolete(Constants.Proposal)] - public class SemanticTokensDocumentProviderOptions - { - /// - /// The server supports deltas for full documents. - /// - [Optional] - public bool? Edits { get; set; } - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensEdit.cs b/src/Protocol/Models/Proposals/SemanticTokensEdit.cs index 153d5dcf5..42984e896 100644 --- a/src/Protocol/Models/Proposals/SemanticTokensEdit.cs +++ b/src/Protocol/Models/Proposals/SemanticTokensEdit.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Immutable; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals { @@ -24,6 +25,7 @@ public class SemanticTokensEdit /// structured pls see /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 /// + [Optional] public ImmutableArray Data { get; set; } = ImmutableArray.Empty; } } diff --git a/src/Protocol/Models/Proposals/SemanticTokensFullOrDelta.cs b/src/Protocol/Models/Proposals/SemanticTokensFullOrDelta.cs new file mode 100644 index 000000000..711f7d130 --- /dev/null +++ b/src/Protocol/Models/Proposals/SemanticTokensFullOrDelta.cs @@ -0,0 +1,36 @@ +using System; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals +{ + [Obsolete(Constants.Proposal)] + public struct SemanticTokensFullOrDelta + { + public SemanticTokensFullOrDelta(SemanticTokensDelta delta) + { + Delta = delta; + Full = null; + } + + public SemanticTokensFullOrDelta(SemanticTokens full) + { + Delta = null; + Full = full; + } + + public bool IsFull => Full != null; + public SemanticTokens Full { get; } + + public bool IsDelta => Delta != null; + public SemanticTokensDelta Delta { get; } + + public static implicit operator SemanticTokensFullOrDelta(SemanticTokensDelta semanticTokensDelta) + { + return new SemanticTokensFullOrDelta(semanticTokensDelta); + } + + public static implicit operator SemanticTokensFullOrDelta(SemanticTokens semanticTokens) + { + return new SemanticTokensFullOrDelta(semanticTokens); + } + } +} diff --git a/src/Protocol/Models/Proposals/SemanticTokensFullOrDeltaPartialResult.cs b/src/Protocol/Models/Proposals/SemanticTokensFullOrDeltaPartialResult.cs new file mode 100644 index 000000000..f4502b4ca --- /dev/null +++ b/src/Protocol/Models/Proposals/SemanticTokensFullOrDeltaPartialResult.cs @@ -0,0 +1,38 @@ +using System; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals +{ + [Obsolete(Constants.Proposal)] + public struct SemanticTokensFullOrDeltaPartialResult + { + public SemanticTokensFullOrDeltaPartialResult( + SemanticTokensPartialResult full) + { + Full = full; + Delta = null; + } + + public SemanticTokensFullOrDeltaPartialResult( + SemanticTokensDeltaPartialResult delta) + { + Full = null; + Delta = delta; + } + + public bool IsDelta => Delta != null; + public SemanticTokensDeltaPartialResult Delta { get; } + + public bool IsFull => Full != null; + public SemanticTokensPartialResult Full { get; } + + public static implicit operator SemanticTokensFullOrDeltaPartialResult(SemanticTokensPartialResult semanticTokensPartialResult) + { + return new SemanticTokensFullOrDeltaPartialResult(semanticTokensPartialResult); + } + + public static implicit operator SemanticTokensFullOrDeltaPartialResult(SemanticTokensDeltaPartialResult semanticTokensDeltaPartialResult) + { + return new SemanticTokensFullOrDeltaPartialResult(semanticTokensDeltaPartialResult); + } + } +} diff --git a/src/Protocol/Models/Proposals/SemanticTokensOptions.cs b/src/Protocol/Models/Proposals/SemanticTokensOptions.cs index 343b8793c..37067e5bf 100644 --- a/src/Protocol/Models/Proposals/SemanticTokensOptions.cs +++ b/src/Protocol/Models/Proposals/SemanticTokensOptions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; @@ -13,7 +14,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals /// @since 3.16.0 /// [Obsolete(Constants.Proposal)] - public class SemanticTokensOptions : StaticTextDocumentRegistrationOptions, ISemanticTokensOptions + public class SemanticTokensOptions : WorkDoneProgressOptions, ISemanticTokensOptions, IStaticRegistrationOptions { /// /// The legend used by the server @@ -25,38 +26,36 @@ public class SemanticTokensOptions : StaticTextDocumentRegistrationOptions, ISem /// of a document. /// [Optional] - public bool RangeProvider { get; set; } + public BooleanOr Range { get; set; } /// /// Server supports providing semantic tokens for a full document. /// [Optional] - public SemanticTokensDocumentProviderOptions DocumentProvider { get; set; } + public BooleanOr Full { get; set; } - public bool WorkDoneProgress { get; set; } - - public static SemanticTokensOptions Of(ISemanticTokensOptions options, - IEnumerable descriptors) + public static SemanticTokensOptions Of(ISemanticTokensOptions options, IEnumerable descriptors) { var result = new SemanticTokensOptions() { WorkDoneProgress = options.WorkDoneProgress, Legend = options.Legend ?? new SemanticTokensLegend(), - DocumentProvider = options.DocumentProvider, - RangeProvider = options.RangeProvider + Full = options.Full, + Range = options.Range }; - if (result.DocumentProvider!= null && result.DocumentProvider.Edits != true) + if (result.Full != null && result.Full?.Value.Delta != true) { - var edits = descriptors.Any(z => z.HandlerType == typeof(ISemanticTokensEditsHandler)); + var edits = descriptors.Any(z => z.HandlerType == typeof(ISemanticTokensDeltaHandler)); if (edits) { - result.DocumentProvider = new Supports(true, - new SemanticTokensDocumentProviderOptions() { - Edits = true - }); + result.Full = new BooleanOr(new SemanticTokensCapabilityRequestFull() { + Delta = true + }); } } return result; } + + public string Id { get; set; } } } diff --git a/src/Protocol/Models/Proposals/SemanticTokensOrSemanticTokensEdits.cs b/src/Protocol/Models/Proposals/SemanticTokensOrSemanticTokensEdits.cs deleted file mode 100644 index 8fd4623e4..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensOrSemanticTokensEdits.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - [Obsolete(Constants.Proposal)] - public struct SemanticTokensOrSemanticTokensEdits - { - public SemanticTokensOrSemanticTokensEdits(SemanticTokensEdits semanticTokensEdits) - { - SemanticTokensEdits = semanticTokensEdits; - SemanticTokens = null; - } - - public SemanticTokensOrSemanticTokensEdits(SemanticTokens semanticTokens) - { - SemanticTokensEdits = null; - SemanticTokens = semanticTokens; - } - - public bool IsSemanticTokens => SemanticTokens != null; - public SemanticTokens SemanticTokens { get; } - - public bool IsSemanticTokensEdits => SemanticTokensEdits != null; - public SemanticTokensEdits SemanticTokensEdits { get; } - - public static implicit operator SemanticTokensOrSemanticTokensEdits(SemanticTokensEdits semanticTokensEdits) - { - return new SemanticTokensOrSemanticTokensEdits(semanticTokensEdits); - } - - public static implicit operator SemanticTokensOrSemanticTokensEdits(SemanticTokens semanticTokens) - { - return new SemanticTokensOrSemanticTokensEdits(semanticTokens); - } - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensParams.cs b/src/Protocol/Models/Proposals/SemanticTokensParams.cs index b8c8b4da7..866977d4e 100644 --- a/src/Protocol/Models/Proposals/SemanticTokensParams.cs +++ b/src/Protocol/Models/Proposals/SemanticTokensParams.cs @@ -7,7 +7,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals /// @since 3.16.0 /// [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.SemanticTokens, Direction.ClientToServer)] + [Method(TextDocumentNames.SemanticTokensFull, Direction.ClientToServer)] public class SemanticTokensParams : IWorkDoneProgressParams, ITextDocumentIdentifierParams, IPartialItemRequest { diff --git a/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs b/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs index 1f47e2b0b..7e27b5a53 100644 --- a/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs +++ b/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs @@ -3,17 +3,9 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals { - /// - /// @since 3.16.0 - /// [Obsolete(Constants.Proposal)] public class SemanticTokensPartialResult { - /// - /// The actual tokens. For a detailed description about how the data is - /// structured pls see - /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 - /// public ImmutableArray Data { get; set; } } } diff --git a/src/Protocol/Models/Proposals/SemanticTokensPartialResultOrSemanticTokensEditsPartialResult.cs b/src/Protocol/Models/Proposals/SemanticTokensPartialResultOrSemanticTokensEditsPartialResult.cs deleted file mode 100644 index 8edffa38f..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensPartialResultOrSemanticTokensEditsPartialResult.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - [Obsolete(Constants.Proposal)] - public struct SemanticTokensPartialResultOrSemanticTokensEditsPartialResult - { - public SemanticTokensPartialResultOrSemanticTokensEditsPartialResult( - SemanticTokensEditsPartialResult semanticTokensEditsPartialResult) - { - SemanticTokensEditsPartialResult = semanticTokensEditsPartialResult; - SemanticTokensPartialResult = null; - } - - public SemanticTokensPartialResultOrSemanticTokensEditsPartialResult( - SemanticTokensPartialResult semanticTokensPartialResult) - { - SemanticTokensEditsPartialResult = null; - SemanticTokensPartialResult = semanticTokensPartialResult; - } - - public bool IsSemanticTokensPartialResult => SemanticTokensPartialResult != null; - public SemanticTokensPartialResult SemanticTokensPartialResult { get; } - - public bool IsSemanticTokensEditsPartialResult => SemanticTokensEditsPartialResult != null; - public SemanticTokensEditsPartialResult SemanticTokensEditsPartialResult { get; } - - public static implicit operator SemanticTokensPartialResultOrSemanticTokensEditsPartialResult( - SemanticTokensEditsPartialResult semanticTokensEditsPartialResult) - { - return new SemanticTokensPartialResultOrSemanticTokensEditsPartialResult(semanticTokensEditsPartialResult); - } - - public static implicit operator SemanticTokensPartialResultOrSemanticTokensEditsPartialResult( - SemanticTokensPartialResult semanticTokensPartialResult) - { - return new SemanticTokensPartialResultOrSemanticTokensEditsPartialResult(semanticTokensPartialResult); - } - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensRegistrationOptions.cs b/src/Protocol/Models/Proposals/SemanticTokensRegistrationOptions.cs index a9d97a04c..5a98423a4 100644 --- a/src/Protocol/Models/Proposals/SemanticTokensRegistrationOptions.cs +++ b/src/Protocol/Models/Proposals/SemanticTokensRegistrationOptions.cs @@ -1,11 +1,15 @@ using System; +using System.Collections.Generic; +using System.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals { [Obsolete(Constants.Proposal)] - public class SemanticTokensRegistrationOptions : StaticWorkDoneTextDocumentRegistrationOptions, - ISemanticTokensOptions + public class SemanticTokensRegistrationOptions : StaticWorkDoneTextDocumentRegistrationOptions, ISemanticTokensOptions { /// /// The legend used by the server @@ -13,17 +17,16 @@ public class SemanticTokensRegistrationOptions : StaticWorkDoneTextDocumentRegis public SemanticTokensLegend Legend { get; set; } /// - /// Server supports providing semantic tokens for a sepcific range + /// Server supports providing semantic tokens for a specific range /// of a document. /// - [Optional] - public bool RangeProvider { get; set; } + public BooleanOr Range { get; set; } /// /// Server supports providing semantic tokens for a full document. /// [Optional] - public SemanticTokensDocumentProviderOptions DocumentProvider { get; set; } + public BooleanOr Full { get; set; } } } diff --git a/src/Protocol/Models/SetTraceParams.cs b/src/Protocol/Models/SetTraceParams.cs new file mode 100644 index 000000000..4dcdd9911 --- /dev/null +++ b/src/Protocol/Models/SetTraceParams.cs @@ -0,0 +1,14 @@ +using MediatR; +using OmniSharp.Extensions.JsonRpc; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + [Method(GeneralNames.SetTrace, Direction.ClientToServer)] + public class SetTraceParams : IRequest + { + /// + /// The new value that should be assigned to the trace setting. + /// + public TraceValue Value { get; set; } + } +} diff --git a/src/Protocol/Models/SignatureInformation.cs b/src/Protocol/Models/SignatureInformation.cs index dce52bcca..e17810199 100644 --- a/src/Protocol/Models/SignatureInformation.cs +++ b/src/Protocol/Models/SignatureInformation.cs @@ -30,7 +30,18 @@ public class SignatureInformation [Optional] public Container Parameters { get; set; } + /// + /// The index of the active parameter. + /// + /// If provided, this is used in place of `SignatureHelp.activeParameter`. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public int? ActiveParameter { get; set; } + private string DebuggerDisplay => $"{Label}{Documentation?.ToString() ?? ""}"; + /// public override string ToString() => DebuggerDisplay; } diff --git a/src/Protocol/Models/InitializeTrace.cs b/src/Protocol/Models/TraceValue.cs similarity index 92% rename from src/Protocol/Models/InitializeTrace.cs rename to src/Protocol/Models/TraceValue.cs index d9d55d723..243396c6a 100644 --- a/src/Protocol/Models/InitializeTrace.cs +++ b/src/Protocol/Models/TraceValue.cs @@ -5,7 +5,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models { [JsonConverter(typeof(StringEnumConverter))] - public enum InitializeTrace + public enum TraceValue { [EnumMember(Value="off")] Off, diff --git a/src/Protocol/Serialization/Converters/SemanticTokensFullOrDeltaConverter.cs b/src/Protocol/Serialization/Converters/SemanticTokensFullOrDeltaConverter.cs new file mode 100644 index 000000000..6c2b59768 --- /dev/null +++ b/src/Protocol/Serialization/Converters/SemanticTokensFullOrDeltaConverter.cs @@ -0,0 +1,42 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters +{ + [Obsolete(Constants.Proposal)] + public class SemanticTokensFullOrDeltaConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, SemanticTokensFullOrDelta value, JsonSerializer serializer) + { + if (value.IsFull) + { + serializer.Serialize(writer, value.Full); + } + else if (value.IsDelta) + { + serializer.Serialize(writer, value.Delta); + } + else + { + writer.WriteNull(); + } + } + + public override SemanticTokensFullOrDelta ReadJson(JsonReader reader, Type objectType, SemanticTokensFullOrDelta existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var obj = JObject.Load(reader); + if (obj.ContainsKey("data")) + { + return new SemanticTokensFullOrDelta(obj.ToObject()); + } + else + { + return new SemanticTokensFullOrDelta(obj.ToObject()); + } + } + + public override bool CanRead => true; + } +} diff --git a/src/Protocol/Serialization/Converters/SemanticTokensFullOrDeltaPartialResultConverter.cs b/src/Protocol/Serialization/Converters/SemanticTokensFullOrDeltaPartialResultConverter.cs new file mode 100644 index 000000000..f131bcd72 --- /dev/null +++ b/src/Protocol/Serialization/Converters/SemanticTokensFullOrDeltaPartialResultConverter.cs @@ -0,0 +1,42 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters +{ + [Obsolete(Constants.Proposal)] + public class SemanticTokensFullOrDeltaPartialResultConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, SemanticTokensFullOrDeltaPartialResult value, JsonSerializer serializer) + { + if (value.IsDelta) + { + serializer.Serialize(writer, value.Delta); + } + else if (value.IsFull) + { + serializer.Serialize(writer, value.Full); + } + else + { + writer.WriteNull(); + } + } + + public override SemanticTokensFullOrDeltaPartialResult ReadJson(JsonReader reader, Type objectType, SemanticTokensFullOrDeltaPartialResult existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var obj = JObject.Load(reader); + if (obj.ContainsKey("data")) + { + return new SemanticTokensFullOrDeltaPartialResult(obj.ToObject()); + } + else + { + return new SemanticTokensFullOrDeltaPartialResult(obj.ToObject()); + } + } + + public override bool CanRead => true; + } +} diff --git a/src/Protocol/Serialization/Converters/SemanticTokensOrSemanticTokensEditsConverter.cs b/src/Protocol/Serialization/Converters/SemanticTokensOrSemanticTokensEditsConverter.cs deleted file mode 100644 index bb0870bc7..000000000 --- a/src/Protocol/Serialization/Converters/SemanticTokensOrSemanticTokensEditsConverter.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters -{ - [Obsolete(Constants.Proposal)] - public class SemanticTokensOrSemanticTokensEditsConverter : JsonConverter - { - public override void WriteJson(JsonWriter writer, SemanticTokensOrSemanticTokensEdits value, JsonSerializer serializer) - { - if (value.IsSemanticTokens) - { - serializer.Serialize(writer, value.SemanticTokens); - } - else if (value.IsSemanticTokensEdits) - { - serializer.Serialize(writer, value.SemanticTokensEdits); - } - else - { - writer.WriteNull(); - } - } - - public override SemanticTokensOrSemanticTokensEdits ReadJson(JsonReader reader, Type objectType, SemanticTokensOrSemanticTokensEdits existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JObject.Load(reader); - if (obj.ContainsKey("data")) - { - return new SemanticTokensOrSemanticTokensEdits(obj.ToObject()); - } - else - { - return new SemanticTokensOrSemanticTokensEdits(obj.ToObject()); - } - } - - public override bool CanRead => true; - } -} diff --git a/src/Protocol/Serialization/Converters/SemanticTokensPartialResultOrSemanticTokensEditsPartialResultConverter.cs b/src/Protocol/Serialization/Converters/SemanticTokensPartialResultOrSemanticTokensEditsPartialResultConverter.cs deleted file mode 100644 index e9082d71a..000000000 --- a/src/Protocol/Serialization/Converters/SemanticTokensPartialResultOrSemanticTokensEditsPartialResultConverter.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters -{ - [Obsolete(Constants.Proposal)] - public class SemanticTokensPartialResultOrSemanticTokensEditsPartialResultConverter : JsonConverter - { - public override void WriteJson(JsonWriter writer, SemanticTokensPartialResultOrSemanticTokensEditsPartialResult value, JsonSerializer serializer) - { - if (value.IsSemanticTokensPartialResult) - { - serializer.Serialize(writer, value.SemanticTokensPartialResult); - } - else if (value.IsSemanticTokensEditsPartialResult) - { - serializer.Serialize(writer, value.SemanticTokensEditsPartialResult); - } - else - { - writer.WriteNull(); - } - } - - public override SemanticTokensPartialResultOrSemanticTokensEditsPartialResult ReadJson(JsonReader reader, Type objectType, SemanticTokensPartialResultOrSemanticTokensEditsPartialResult existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JObject.Load(reader); - if (obj.ContainsKey("start")) - { - return new SemanticTokensPartialResultOrSemanticTokensEditsPartialResult(obj.ToObject()); - } - else - { - return new SemanticTokensPartialResultOrSemanticTokensEditsPartialResult(obj.ToObject()); - } - } - - public override bool CanRead => true; - } -} diff --git a/src/Protocol/Serialization/Serializer.cs b/src/Protocol/Serialization/Serializer.cs index db1722d27..82340d328 100644 --- a/src/Protocol/Serialization/Serializer.cs +++ b/src/Protocol/Serialization/Serializer.cs @@ -102,8 +102,8 @@ protected override void AddOrReplaceConverters(ICollection conver ReplaceConverter(converters, new ProgressTokenConverter()); ReplaceConverter(converters, new MarkedStringsOrMarkupContentConverter()); ReplaceConverter(converters, new CommandOrCodeActionConverter()); - ReplaceConverter(converters, new SemanticTokensOrSemanticTokensEditsConverter()); - ReplaceConverter(converters, new SemanticTokensPartialResultOrSemanticTokensEditsPartialResultConverter()); + ReplaceConverter(converters, new SemanticTokensFullOrDeltaConverter()); + ReplaceConverter(converters, new SemanticTokensFullOrDeltaPartialResultConverter()); ReplaceConverter(converters, new SymbolInformationOrDocumentSymbolConverter()); ReplaceConverter(converters, new LocationOrLocationLinkConverter()); ReplaceConverter(converters, new WorkspaceEditDocumentChangeConverter()); diff --git a/src/Protocol/Server/Capabilities/TextDocumentSyncOptions.cs b/src/Protocol/Server/Capabilities/TextDocumentSyncOptions.cs index 083da0d8e..6496d6df6 100644 --- a/src/Protocol/Server/Capabilities/TextDocumentSyncOptions.cs +++ b/src/Protocol/Server/Capabilities/TextDocumentSyncOptions.cs @@ -33,7 +33,7 @@ public class TextDocumentSyncOptions : ITextDocumentSyncOptions /// Save notifications are sent to the server. /// [Optional] - public SaveOptions Save { get; set; } + public BooleanOr Save { get; set; } public static TextDocumentSyncOptions Of(IEnumerable options, IEnumerable descriptors) { @@ -52,7 +52,7 @@ public static TextDocumentSyncOptions Of(IEnumerable o WillSaveWaitUntil = options.Any(z => z.WillSaveWaitUntil), Save = new SaveOptions() { - IncludeText = options.Any(z => z.Save?.IncludeText == true) + IncludeText = options.Any(z => z.Save.IsValue && z.Save.Value.IncludeText) } }; } diff --git a/src/Protocol/Server/ISetTraceHandler.cs b/src/Protocol/Server/ISetTraceHandler.cs new file mode 100644 index 000000000..7f56de2aa --- /dev/null +++ b/src/Protocol/Server/ISetTraceHandler.cs @@ -0,0 +1,21 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Server +{ + [Parallel, Method(GeneralNames.SetTrace, Direction.ClientToServer)] + [GenerateHandlerMethods, GenerateRequestMethods(typeof(IClientLanguageClient), typeof(ILanguageClient))] + public interface ISetTraceHandler : IJsonRpcNotificationHandler + { + } + + public abstract class SetTraceHandler : ISetTraceHandler + { + public abstract Task Handle(SetTraceParams request, CancellationToken cancellationToken); + } +} diff --git a/src/Protocol/TextDocumentNames.cs b/src/Protocol/TextDocumentNames.cs index 7f9e2b737..c4fbac49f 100644 --- a/src/Protocol/TextDocumentNames.cs +++ b/src/Protocol/TextDocumentNames.cs @@ -43,9 +43,9 @@ public static class TextDocumentNames [Obsolete(Constants.Proposal)] public const string CallHierarchyOutgoing = "callHierarchy/outgoingCalls"; [Obsolete(Constants.Proposal)] - public const string SemanticTokens = "textDocument/semanticTokens"; + public const string SemanticTokensFull = "textDocument/semanticTokens/full"; [Obsolete(Constants.Proposal)] - public const string SemanticTokensEdits = "textDocument/semanticTokens/edits"; + public const string SemanticTokensFullDelta = "textDocument/semanticTokens/full/delta"; [Obsolete(Constants.Proposal)] public const string SemanticTokensRange = "textDocument/semanticTokens/range"; } diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index ac3f45af4..3b9ea995b 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -267,7 +267,7 @@ async Task IRequestHandler { ClientSettings = request; - if (request.Trace == InitializeTrace.Verbose) + if (request.TraceValue == TraceValue.Verbose) { var loggerSettings = _serviceProvider.GetService(); diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets index b40df5318..c0cc296fd 100644 --- a/test/Directory.Build.targets +++ b/test/Directory.Build.targets @@ -7,8 +7,8 @@ - - + + diff --git a/test/JsonRpc.Tests/AutoNSubstitute/AutoSubstitute.cs b/test/JsonRpc.Tests/AutoNSubstitute/AutoSubstitute.cs index 5aa9a0842..0da008393 100644 --- a/test/JsonRpc.Tests/AutoNSubstitute/AutoSubstitute.cs +++ b/test/JsonRpc.Tests/AutoNSubstitute/AutoSubstitute.cs @@ -1,133 +1,163 @@ using System; -using Autofac; -using Autofac.Builder; -using Autofac.Core; -using Autofac.Features.ResolveAnything; +using System.Collections.Concurrent; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using DryIoc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; // ReSharper disable once CheckNamespace namespace NSubstitute.Internals { - /// - /// Auto mocking container using and . +/// + /// Automatically creates substitute for requested services that haven't been registered /// public class AutoSubstitute : IDisposable { - /// - /// Create an AutoSubstitute, but modify the before building a container. + /// Create a container that automatically substitutes unknown types. /// - /// Action to modify the - public AutoSubstitute(Action builderModifier) + /// + /// + public AutoSubstitute( + IContainer? container = null, + Func? configureAction = null) { - var builder = new ContainerBuilder(); + Container = container ?? new Container(); - builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource()); - builder.RegisterSource(new NSubstituteRegistrationHandler()); + Container = Container - builderModifier(builder); + .With(rules => rules + .WithTestLoggerResolver((request, loggerType) => ActivatorUtilities.CreateInstance(request.Container, loggerType)) + .WithUndefinedTestDependenciesResolver(request => Substitute.For(new[] { request.ServiceType }, null)) + .WithConcreteTypeDynamicRegistrations((type, o) => true, Reuse.Transient) + ); - Container = builder.Build(); + if (configureAction != null) + { + Container = configureAction.Invoke(Container); + } } /// - /// that handles the component resolution. + /// Gets the that handles the component resolution. /// public IContainer Container { get; } /// - /// Cleans up the . + /// Resolve the specified type in the container (register it if needed). /// - public void Dispose() - { - Container.Dispose(); - } - - /// - /// Resolve the specified type from the container. - /// - /// The type to resolve - /// Optional constructor parameters - /// The resolved object - public T Resolve(params Parameter[] parameters) - { - return Container.Resolve(parameters); - } - - /// - /// Register the specified implementation type to the container as the specified service type and resolve it using the given parameters. - /// - /// The type to register the implementation as - /// The implementation type - /// Optional constructor parameters - /// The resolved service instance - public TService Provide(params Parameter[] parameters) - { - Container.ComponentRegistry.Register(RegistrationBuilder.ForType() - .As().InstancePerLifetimeScope().CreateRegistration() - ); - - return Container.Resolve(parameters); - } + /// The type of the service. + /// The service. + public T Resolve() => Container.Resolve(); /// - /// Register the specified object to the container as the specified service type and resolve it. + /// Resolve the specified type in the container (register specified instance if needed). /// - /// The type to register the object as - /// The object to register into the container - /// The instance resolved from container + /// The type of the service. + /// The instance to register if needed. + /// The instance resolved from container. + [SuppressMessage( + "Microsoft.Reliability", + "CA2000:Dispose objects before losing scope", + Justification = "The component registry is responsible for registration disposal." + )] public TService Provide(TService instance) where TService : class { - Container.ComponentRegistry.Register(RegistrationBuilder.ForDelegate((c, p) => instance) - .InstancePerLifetimeScope().CreateRegistration() - ); - - return Container.Resolve(); + Container.RegisterInstance(instance); + return instance; } /// - /// Register the specified object to the container as the specified keyed service type and resolve it. + /// Resolve the specified type in the container (register specified instance if needed). /// - /// The type to register the object as - /// The object to register into the container - /// The key to register the service with - /// The instance resolved from container - public TService Provide(TService instance, object serviceKey) - where TService : class + /// The type of the service. + /// The type of the implementation. + /// The instance resolved from container. + [SuppressMessage( + "Microsoft.Reliability", + "CA2000:Dispose objects before losing scope", + Justification = "The component registry is responsible for registration disposal." + )] + public TService Provide() where TImplementation : TService { - Container.ComponentRegistry.Register(RegistrationBuilder.ForDelegate((c, p) => instance).As(new KeyedService(serviceKey, typeof(TService))) - .InstancePerLifetimeScope().CreateRegistration() - ); - + Container.Register(); return Container.Resolve(); } + void IDisposable.Dispose() => Container.Dispose(); + } + + public static class DryIocExtensions + { /// - /// Registers to the container and returns a substitute for a given concrete class given the explicit constructor parameters. - /// This is used for concrete classes where NSubstitutes won't be created by default by the container when using Resolve. - /// For advanced uses consider using directly and then calling so that type is used on dependencies for other Resolved types. + /// Adds support for resolving generic ILoggers from the DI Container and allowing the loggers to be wrapped + /// if desired /// - /// The type to register and return a substitute for - /// Optional constructor parameters - /// The instance resolved from the container - public TService For(params object[] parameters) where TService : class + /// + /// + /// + public static Rules WithTestLoggerResolver(this Rules rules, Func creator) { - var substitute = Substitute.For(parameters); - return Provide(substitute); + var dictionary = new ConcurrentDictionary(); + return rules.WithUnknownServiceResolvers( + (rules.UnknownServiceResolvers ?? Array.Empty()).ToImmutableList().Add( + request => + { + var serviceType = request.ServiceType; + if (!serviceType.IsInterface || !serviceType.IsGenericType || + serviceType.GetGenericTypeDefinition() != typeof(ILogger<>)) + { + return null; + } + + if (!dictionary.TryGetValue(serviceType, out var instance)) + { + var loggerType = typeof(Logger<>).MakeGenericType( + request.ServiceType.GetGenericArguments()[0] + ); + instance = new DelegateFactory(_ => creator(request, loggerType), Reuse.Singleton); + dictionary.TryAdd(serviceType, instance); + } + + return instance; + } + ).ToArray() + ); } /// - /// Registers to the container and returns a substitute for a given concrete class using autofac to resolve the constructor parameters. - /// This is used for concrete classes where NSubstitutes won't be created by default by the container when using Resolve. - /// For advanced uses consider using directly and then calling so that type is used on dependencies for other Resolved types. + /// Adds support for auto stub/mock/faking dependencies that are not already in the container. /// - /// The type to register and return a substitute for - /// Any constructor parameters that Autofac can't resolve automatically - /// The instance resolved from the container - public TService For(params Parameter[] parameters) where TService : class + /// + /// + /// + public static Rules WithUndefinedTestDependenciesResolver(this Rules rules, Func creator) { - var substitute = Resolve(parameters); - return Provide(substitute); + var dictionary = new ConcurrentDictionary(); + return rules.WithUnknownServiceResolvers( + (rules.UnknownServiceResolvers ?? Array.Empty()).ToImmutableList().Add( + request => + { + var serviceType = request.ServiceType; + if (!serviceType.IsAbstract) + return null; // Mock interface or abstract class only. + + if (request.Is(parameter: info => info.IsOptional)) + return null; // Ignore optional parameters + + if (!dictionary.TryGetValue(serviceType, out var instance)) + { + instance = new DelegateFactory(_ => creator(request), Reuse.Singleton); + dictionary.TryAdd(serviceType, instance); + } + + return instance; + } + ).ToArray() + ); } } } diff --git a/test/JsonRpc.Tests/AutoNSubstitute/AutoTestBase.cs b/test/JsonRpc.Tests/AutoNSubstitute/AutoTestBase.cs index a7a2c4250..887a9b35f 100644 --- a/test/JsonRpc.Tests/AutoNSubstitute/AutoTestBase.cs +++ b/test/JsonRpc.Tests/AutoNSubstitute/AutoTestBase.cs @@ -1,6 +1,6 @@ using System; -using Autofac; -using Autofac.Extensions.DependencyInjection; +using DryIoc; +using DryIoc.Microsoft.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NSubstitute.Internals; @@ -12,13 +12,14 @@ namespace NSubstitute public abstract class AutoTestBase { private AutoSubstitute _autoSubstitute; - private readonly Action _action; + private readonly Action _action; + protected AutoTestBase(ITestOutputHelper testOutputHelper) : this(testOutputHelper, cb => { }) { } - protected AutoTestBase(ITestOutputHelper testOutputHelper, Action action) + protected AutoTestBase(ITestOutputHelper testOutputHelper, Action action) { LoggerFactory = new TestLoggerFactory(testOutputHelper); Logger = LoggerFactory.CreateLogger("default"); @@ -34,7 +35,12 @@ protected AutoTestBase(ITestOutputHelper testOutputHelper, Action _autoSubstitute ?? (_autoSubstitute = new AutoSubstitute(_action)); + + public AutoSubstitute AutoSubstitute => _autoSubstitute ??= new AutoSubstitute(new Container().WithDependencyInjectionAdapter(), _ => { + _action(_); + return _; + }); + public IServiceProvider ServiceProvider => AutoSubstitute.Container.Resolve(); } } diff --git a/test/JsonRpc.Tests/AutoNSubstitute/NSubstituteRegistrationHandler.cs b/test/JsonRpc.Tests/AutoNSubstitute/NSubstituteRegistrationHandler.cs deleted file mode 100644 index 9d4088c98..000000000 --- a/test/JsonRpc.Tests/AutoNSubstitute/NSubstituteRegistrationHandler.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Autofac; -using Autofac.Builder; -using Autofac.Core; -using MediatR; - -// ReSharper disable once CheckNamespace -namespace NSubstitute -{ - /// Resolves unknown interfaces and Mocks using the . - internal class NSubstituteRegistrationHandler : IRegistrationSource - { - private static readonly IReadOnlyCollection GenericCollectionTypes = new List - { - typeof(IEnumerable<>), - typeof(IList<>), - typeof(IReadOnlyCollection<>), - typeof(ICollection<>), - typeof(IReadOnlyList<>) - }; - - /// - /// Retrieve a registration for an unregistered service, to be used - /// by the container. - /// - /// The service that was requested. - /// - /// - /// Registrations for the service. - /// - public IEnumerable RegistrationsFor - (Service service, Func> registrationAccessor) - { - if (service == null) - throw new ArgumentNullException(nameof(service)); - - if (!(service is IServiceWithType typedService) || - !typedService.ServiceType.IsInterface || - IsGenericListOrCollectionInterface(typedService.ServiceType) || - (typedService.ServiceType.IsGenericType && typedService.ServiceType.GetGenericTypeDefinition() == typeof(IPipelineBehavior<,>)) || - typedService.ServiceType.IsArray || - typeof(IStartable).IsAssignableFrom(typedService.ServiceType)) - return Enumerable.Empty(); - - var registrations = registrationAccessor(service); - var componentRegistrations = registrations as IComponentRegistration[] ?? registrations.ToArray(); - if (componentRegistrations.Any()) - return componentRegistrations; - - var rb = RegistrationBuilder.ForDelegate((c, p) => Substitute.For(new[] { typedService.ServiceType }, null)) - .As(service) - .InstancePerLifetimeScope(); - - return new[] { rb.CreateRegistration() }; - } - - public bool IsAdapterForIndividualComponents => false; - - private static bool IsGenericListOrCollectionInterface(Type serviceType) - { - return serviceType.IsGenericType && GenericCollectionTypes.Contains(serviceType.GetGenericTypeDefinition()); - } - } -} diff --git a/test/Lsp.Tests/Capabilities/Client/ClientCapabilitiesTests_$SimpleTest.json b/test/Lsp.Tests/Capabilities/Client/ClientCapabilitiesTests_$SimpleTest.json index a186d78e0..08cf1d8fd 100644 --- a/test/Lsp.Tests/Capabilities/Client/ClientCapabilitiesTests_$SimpleTest.json +++ b/test/Lsp.Tests/Capabilities/Client/ClientCapabilitiesTests_$SimpleTest.json @@ -29,7 +29,9 @@ "snippetSupport": true, "commitCharactersSupport": false, "deprecatedSupport": false, - "preselectSupport": false + "preselectSupport": false, + "insertReplaceSupport": false, + "resolveAdditionalTextEditsSupport": false }, "contextSupport": false, "dynamicRegistration": true diff --git a/test/Lsp.Tests/Capabilities/Client/CompletionCapabilityTests_$SimpleTest.json b/test/Lsp.Tests/Capabilities/Client/CompletionCapabilityTests_$SimpleTest.json index 7c63bc399..26781aec2 100644 --- a/test/Lsp.Tests/Capabilities/Client/CompletionCapabilityTests_$SimpleTest.json +++ b/test/Lsp.Tests/Capabilities/Client/CompletionCapabilityTests_$SimpleTest.json @@ -3,7 +3,9 @@ "snippetSupport": false, "commitCharactersSupport": false, "deprecatedSupport": false, - "preselectSupport": false + "preselectSupport": false, + "insertReplaceSupport": false, + "resolveAdditionalTextEditsSupport": false }, "contextSupport": false, "dynamicRegistration": false diff --git a/test/Lsp.Tests/Capabilities/Client/CompletionItemCapabilityTests_$SimpleTest.json b/test/Lsp.Tests/Capabilities/Client/CompletionItemCapabilityTests_$SimpleTest.json index 662e036b4..923349684 100644 --- a/test/Lsp.Tests/Capabilities/Client/CompletionItemCapabilityTests_$SimpleTest.json +++ b/test/Lsp.Tests/Capabilities/Client/CompletionItemCapabilityTests_$SimpleTest.json @@ -2,5 +2,7 @@ "snippetSupport": true, "commitCharactersSupport": false, "deprecatedSupport": false, - "preselectSupport": false + "preselectSupport": false, + "insertReplaceSupport": false, + "resolveAdditionalTextEditsSupport": false } diff --git a/test/Lsp.Tests/Capabilities/Client/TextDocumentClientCapabilitiesTests_$SimpleTest.json b/test/Lsp.Tests/Capabilities/Client/TextDocumentClientCapabilitiesTests_$SimpleTest.json index ff06981ec..b4afaac94 100644 --- a/test/Lsp.Tests/Capabilities/Client/TextDocumentClientCapabilitiesTests_$SimpleTest.json +++ b/test/Lsp.Tests/Capabilities/Client/TextDocumentClientCapabilitiesTests_$SimpleTest.json @@ -10,7 +10,9 @@ "snippetSupport": true, "commitCharactersSupport": false, "deprecatedSupport": false, - "preselectSupport": false + "preselectSupport": false, + "insertReplaceSupport": false, + "resolveAdditionalTextEditsSupport": false }, "contextSupport": false, "dynamicRegistration": true diff --git a/test/Lsp.Tests/FoundationTests.cs b/test/Lsp.Tests/FoundationTests.cs index 51804f090..bc6a53d59 100644 --- a/test/Lsp.Tests/FoundationTests.cs +++ b/test/Lsp.Tests/FoundationTests.cs @@ -493,7 +493,7 @@ public class TypeHandlerExtensionData : TheoryData x.Method == TextDocumentNames.SemanticTokens); + client.RegistrationManager.CurrentRegistrations.Should().Contain(x => x.Method == TextDocumentNames.SemanticTokensFull); } [Fact] @@ -179,7 +179,7 @@ public async Task Should_Register_Static_When_Dynamic_Is_Disabled() } }, x => x.ConfigureForSupports().Excluding(z => z.DynamicRegistration)); - client.RegistrationManager.CurrentRegistrations.Should().NotContain(x => x.Method == TextDocumentNames.SemanticTokens); + client.RegistrationManager.CurrentRegistrations.Should().NotContain(x => x.Method == TextDocumentNames.SemanticTokensFull); } private void ConfigureClient(LanguageClientOptions options) diff --git a/test/Lsp.Tests/Models/InitializeParamsTests.cs b/test/Lsp.Tests/Models/InitializeParamsTests.cs index 2a7e23eac..4531dd105 100644 --- a/test/Lsp.Tests/Models/InitializeParamsTests.cs +++ b/test/Lsp.Tests/Models/InitializeParamsTests.cs @@ -75,7 +75,7 @@ public void SimpleTest(string expected) InitializationOptions = null, ProcessId = 1234, RootUri = new Uri("file:///file/abc/12.cs"), - Trace = InitializeTrace.Verbose + TraceValue = TraceValue.Verbose }; var result = Fixture.SerializeObject(model); diff --git a/test/Lsp.Tests/Models/InitializeParamsTests_$SimpleTest.json b/test/Lsp.Tests/Models/InitializeParamsTests_$SimpleTest.json index b04f87e6c..0892168b7 100644 --- a/test/Lsp.Tests/Models/InitializeParamsTests_$SimpleTest.json +++ b/test/Lsp.Tests/Models/InitializeParamsTests_$SimpleTest.json @@ -31,7 +31,9 @@ "snippetSupport": true, "commitCharactersSupport": false, "deprecatedSupport": false, - "preselectSupport": false + "preselectSupport": false, + "insertReplaceSupport": false, + "resolveAdditionalTextEditsSupport": false }, "contextSupport": false, "dynamicRegistration": true @@ -90,6 +92,6 @@ "abc": "test" } }, - "trace": "verbose", + "traceValue": "verbose", "workspaceFolders": null } diff --git a/test/Lsp.Tests/Models/SignatureHelpTests_$SimpleTest.json b/test/Lsp.Tests/Models/SignatureHelpTests_$SimpleTest.json index e562d4da3..e057610fa 100644 --- a/test/Lsp.Tests/Models/SignatureHelpTests_$SimpleTest.json +++ b/test/Lsp.Tests/Models/SignatureHelpTests_$SimpleTest.json @@ -13,4 +13,4 @@ ], "activeSignature": 2, "activeParameter": 1 -} \ No newline at end of file +} diff --git a/test/Lsp.Tests/SemanticTokensDocumentTests.cs b/test/Lsp.Tests/SemanticTokensDocumentTests.cs index 7644ba9cb..54b2cb13f 100644 --- a/test/Lsp.Tests/SemanticTokensDocumentTests.cs +++ b/test/Lsp.Tests/SemanticTokensDocumentTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using Bogus; @@ -52,20 +53,14 @@ public void ReturnDocumentTokensFromScratch() var data = Normalize(ExampleDocumentText, result.Data).ToArray(); _logger.LogInformation("Some Data {Data}", data.AsEnumerable()); var expectedResponse = new NormalizedToken[] { - "using (member:static|abstract)", "System (member:static|abstract)", "using (parameter:none)", - "System (string:none)", "Collections (namespace:deprecated)", "Generic (type:none)", - "using (property:none)", "System (documentation:definition|abstract)", - "Linq (documentation:definition)", "using (documentation:none)", "System (label:none)", - "Text (documentation:definition|abstract)", "using (documentation:none)", - "System (documentation:documentation)", "Threading (documentation:definition|readonly)", - "Tasks (documentation:none)", "namespace (documentation:abstract)", - "CSharpTutorials (documentation:none)", "{ (type:documentation)", "class (label:none)", - "Program (documentation:none)", "{ (documentation:none)", "static (number:documentation)", - "void (function:none)", "Main (function:none)", "string[] (function:documentation|static)", - "args (function:none)", "{ (struct:declaration|abstract)", "string (type:none)", "message (class:none)", - "= (macro:none)", "Hello (documentation:none)", "World!! (class:none)", "Console (struct:definition)", - "WriteLine (parameter:definition|readonly)", "message (struct:definition)", "} (regexp:none)", - "} (class:static|abstract)", "} (enum:declaration|definition)" + "using (macro:async|deprecated)", "System (macro:async|deprecated)", "using (event:none)", "System (number:none)", "Collections (struct:readonly)", + "Generic (class:none)", "using (variable:modification|defaultLibrary)", "System (comment:static|deprecated)", "Linq (comment:definition)", "using (comment:none)", + "System (enumMember:none)", "Text (comment:static|deprecated)", "using (comment:none)", "System (comment:declaration)", "Threading (comment:static|defaultLibrary)", + "Tasks (comment:none)", "namespace (comment:readonly)", "CSharpTutorials (comment:none)", "{ (struct:documentation)", "class (enumMember:none)", + "Program (comment:none)", "{ (comment:none)", "static (regexp:documentation)", "void (macro:none)", "Main (macro:none)", "string[] (property:declaration|abstract)", + "args (macro:none)", "{ (interface:documentation|declaration|deprecated)", "string (struct:none)", "message (enum:none)", "= (label:none)", "Hello (comment:none)", + "World!! (enum:none)", "Console (interface:static)", "WriteLine (event:async|modification)", "message (interface:static)", "} (operator:none)", + "} (enum:async|deprecated)", "} (function:declaration|async)" }; data.Should().ContainInOrder(expectedResponse); } @@ -105,8 +100,7 @@ public ReturnDocumentTokensFromScratch_ForRange_Data() } }, new NormalizedToken[] { - "ssage (class:none)", "= (macro:none)", "Hello (documentation:none)", "World!! (class:none)", - "Console (struct:definition)", "WriteLi (parameter:definition|readonly)" + "ssage (enum:none)", "= (label:none)", "Hello (comment:none)", "World!! (enum:none)", "Console (interface:static)", "WriteLi (event:async|modification)" } ); Add( @@ -121,13 +115,10 @@ public ReturnDocumentTokensFromScratch_ForRange_Data() } }, new NormalizedToken[] { - "using (member:static|abstract)", "System (member:static|abstract)", "using (parameter:none)", - "System (string:none)", "Collections (namespace:deprecated)", "Generic (type:none)", - "using (property:none)", "System (documentation:definition|abstract)", - "Linq (documentation:definition)", "using (documentation:none)", "System (label:none)", - "Text (documentation:definition|abstract)", "using (documentation:none)", - "System (documentation:documentation)", "Threading (documentation:definition|readonly)", - "Tasks (documentation:none)" + "using (macro:async|deprecated)", "System (macro:async|deprecated)", "using (event:none)", "System (number:none)", "Collections (struct:readonly)", + "Generic (class:none)", "using (variable:modification|defaultLibrary)", "System (comment:static|deprecated)", "Linq (comment:definition)", + "using (comment:none)", "System (enumMember:none)", "Text (comment:static|deprecated)", "using (comment:none)", "System (comment:declaration)", + "Threading (comment:static|defaultLibrary)", "Tasks (comment:none)" } ); Add( @@ -142,8 +133,7 @@ public ReturnDocumentTokensFromScratch_ForRange_Data() } }, new NormalizedToken[] { - "Console (struct:definition)", "WriteLine (parameter:definition|readonly)", - "message (struct:definition)" + "Console (interface:static)", "WriteLine (event:async|modification)", "message (interface:static)" } ); } @@ -163,7 +153,7 @@ public void ReturnDocumentEdits(string originalText, string modifiedText, Tokenize(originalText, builder); builder.Commit(); originalTokens = document.GetSemanticTokens(); - builder = document.Edit(new SemanticTokensEditsParams() { + builder = document.Edit(new SemanticTokensDeltaParams() { PreviousResultId = document.Id, }); Tokenize(modifiedText, builder); @@ -171,8 +161,8 @@ public void ReturnDocumentEdits(string originalText, string modifiedText, } var result = document.GetSemanticTokensEdits(); - result.IsSemanticTokensEdits.Should().BeTrue(); - var edits = result.SemanticTokensEdits; + result.IsDelta.Should().BeTrue(); + var edits = result.Delta; edits.ResultId.Should().Be(document.Id); edits.Edits.Should().HaveCount(1); @@ -195,29 +185,22 @@ public ReturnDocumentEdits_Data() ExampleDocumentText, ExampleDocumentText.Replace("namespace CSharpTutorials", "namespace Something.Else.Entirely"), new NormalizedToken[] { - "using (member:static|abstract)", "System (member:static|abstract)", "using (parameter:none)", - "System (string:none)", "Collections (namespace:deprecated)", "Generic (type:none)", - "using (property:none)", "System (documentation:definition|abstract)", - "Linq (documentation:definition)", "using (documentation:none)", "System (label:none)", - "Text (documentation:definition|abstract)", "using (documentation:none)", - "System (documentation:documentation)", "Threading (documentation:definition|readonly)", - "Tasks (documentation:none)", "namespace (function:readonly)", "Something (function:readonly)", - "Else (class:abstract)", "Entirely (regexp:documentation|abstract|deprecated)", - "{ (type:documentation)", "class (label:none)", "Program (documentation:none)", - "{ (documentation:none)", "static (number:documentation)", "void (function:none)", - "Main (function:none)", "string[] (function:documentation|static)", "args (function:none)", - "{ (struct:declaration|abstract)", "string (type:none)", "message (class:none)", - "= (macro:none)", "Hello (documentation:none)", "World!! (class:none)", - "Console (struct:definition)", "WriteLine (parameter:definition|readonly)", - "message (struct:definition)", "} (regexp:none)", "} (class:static|abstract)", - "} (enum:declaration|definition)" + "using (macro:async|deprecated)", "System (macro:async|deprecated)", "using (event:none)", "System (number:none)", "Collections (struct:readonly)", + "Generic (class:none)", "using (variable:modification|defaultLibrary)", "System (comment:static|deprecated)", "Linq (comment:definition)", + "using (comment:none)", "System (enumMember:none)", "Text (comment:static|deprecated)", "using (comment:none)", "System (comment:declaration)", + "Threading (comment:static|defaultLibrary)", "Tasks (comment:none)", "namespace (property:defaultLibrary)", "Something (property:defaultLibrary)", + "Else (enum:deprecated)", "Entirely (operator:declaration|deprecated|modification)", "{ (struct:documentation)", "class (enumMember:none)", + "Program (comment:none)", "{ (comment:none)", "static (regexp:documentation)", "void (macro:none)", "Main (macro:none)", + "string[] (property:declaration|abstract)", "args (macro:none)", "{ (interface:documentation|declaration|deprecated)", "string (struct:none)", + "message (enum:none)", "= (label:none)", "Hello (comment:none)", "World!! (enum:none)", "Console (interface:static)", + "WriteLine (event:async|modification)", "message (interface:static)", "} (operator:none)", "} (enum:async|deprecated)", "} (function:declaration|async)" }); Add("using", "using System;", new NormalizedToken[] { - "using (member:static|abstract)", "System (member:static|abstract)" + "using (macro:async|deprecated)", "System (macro:async|deprecated)" }); Add("using System;", "using", new NormalizedToken[] { - "using (member:static|abstract)" + "using (macro:async|deprecated)" }); } } @@ -277,6 +260,7 @@ private string ExtractRange(string document, Range range) return sb.ToString(); } + [DebuggerDisplay("{ToString()}")] public class NormalizedToken : IEquatable, IEquatable { public NormalizedToken(string text, SemanticTokenType type, params SemanticTokenModifier[] modifiers) From fa708013adb160a4149b7de5dfd261d04ca30624 Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Wed, 22 Jul 2020 22:34:28 -0400 Subject: [PATCH 02/10] 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. --- sample/SampleServer/Program.cs | 11 +- src/Client/LanguageClient.cs | 1 + src/Client/RegistrationManager.cs | 13 +- src/JsonRpc.Testing/AggregateSettler.cs | 2 +- src/JsonRpc.Testing/Settler.cs | 8 +- src/JsonRpc/CompositeHandlersManager.cs | 2 + src/JsonRpc/HandlerCollection.cs | 54 +- src/JsonRpc/IHandlersManager.cs | 1 + src/JsonRpc/JsonRpcOptionsRegistryBase.cs | 10 + src/JsonRpc/JsonRpcServer.cs | 1 + src/JsonRpc/JsonRpcServerOptionsBase.cs | 6 + src/Protocol/AbstractHandlers.cs | 2 + .../Client/IRegisterCapabilityHandler.cs | 2 +- .../Client/IUnregisterCapabilityHandler.cs | 2 +- src/Protocol/Window/ILogMessageHandler.cs | 25 + src/Server/LanguageServer.cs | 29 +- src/Shared/SharedHandlerCollection.cs | 56 +- test/JsonRpc.Tests/IntegrationTests.cs | 25 + ...tionIdTests.cs => SpecificatiosIdTests.cs} | 2 +- .../Server/SpecifictionRecieverTests.cs | 2 +- .../ConnectionAndDisconnectionTests.cs | 34 + .../Integration/DynamicRegistrationTests.cs | 51 +- .../Lsp.Tests/Integration/PartialItemTests.cs | 2 +- vscode-testextension/package-lock.json | 588 ++++-------------- vscode-testextension/package.json | 10 +- vscode-testextension/src/extension.ts | 4 +- 26 files changed, 425 insertions(+), 518 deletions(-) rename test/JsonRpc.Tests/Server/{SpecifictionIdTests.cs => SpecificatiosIdTests.cs} (98%) diff --git a/sample/SampleServer/Program.cs b/sample/SampleServer/Program.cs index 0226f4b71..b872475aa 100644 --- a/sample/SampleServer/Program.cs +++ b/sample/SampleServer/Program.cs @@ -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; @@ -37,8 +41,10 @@ static async Task MainAsync(string[] args) var server = await LanguageServer.From(options => options + .WithInput(Console.OpenStandardInput()) + .WithOutput(Console.OpenStandardOutput()) .ConfigureLogging(x => x - .AddSerilog() + .AddSerilog(Log.Logger) .AddLanguageProtocolLogging() .SetMinimumLevel(LogLevel.Debug)) .WithHandler() @@ -47,6 +53,9 @@ static async Task MainAsync(string[] args) .WithHandler() .WithHandler() .WithHandler() + // Linking here because the spec changed but vscode is behind + .WithLink(TextDocumentNames.SemanticTokensFull, "textDocument/semanticTokens") + .WithLink(TextDocumentNames.SemanticTokensFullDelta, "textDocument/semanticTokens/edits") .WithServices(x => x.AddLogging(b => b.SetMinimumLevel(LogLevel.Trace))) .WithServices(services => { services.AddSingleton(provider => { diff --git a/src/Client/LanguageClient.cs b/src/Client/LanguageClient.cs index c40da94bd..faa999ae9 100644 --- a/src/Client/LanguageClient.cs +++ b/src/Client/LanguageClient.cs @@ -200,6 +200,7 @@ internal LanguageClient(LanguageClientOptions options) : base(options) var serviceIdentifiers = _serviceProvider.GetServices().ToArray(); _disposable.Add(_textDocumentIdentifiers.Add(serviceIdentifiers)); _disposable.Add(_collection.Add(serviceHandlers)); + options.AddLinks(_collection); } public ITextDocumentLanguageClient TextDocument { get; } diff --git a/src/Client/RegistrationManager.cs b/src/Client/RegistrationManager.cs index aed6cae84..57e4284f8 100644 --- a/src/Client/RegistrationManager.cs +++ b/src/Client/RegistrationManager.cs @@ -36,16 +36,23 @@ public RegistrationManager(ISerializer serializer, ILogger Task IRequestHandler.Handle(RegistrationParams request, CancellationToken cancellationToken) { - Register(request.Registrations.ToArray()); + lock (this) + { + Register(request.Registrations.ToArray()); + } + _registrationSubject.OnNext(_registrations.Values); return Unit.Task; } Task IRequestHandler.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); diff --git a/src/JsonRpc.Testing/AggregateSettler.cs b/src/JsonRpc.Testing/AggregateSettler.cs index 7967a6b6b..967c3269f 100644 --- a/src/JsonRpc.Testing/AggregateSettler.cs +++ b/src/JsonRpc.Testing/AggregateSettler.cs @@ -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(); diff --git a/src/JsonRpc.Testing/Settler.cs b/src/JsonRpc.Testing/Settler.cs index f1a46afae..3587bf542 100644 --- a/src/JsonRpc.Testing/Settler.cs +++ b/src/JsonRpc.Testing/Settler.cs @@ -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()) - .Switch() .Replay(1) - .RefCount(); + .RefCount() + .Select(z => z <= 0 ? Observable.Timer(waitTime).Select(_ => Unit.Default).Timeout(timeout, Observable.Return(Unit.Default)) : Observable.Never()) + .Switch(); _requester = subject; } @@ -43,7 +43,7 @@ public Task SettleNext() public IObservable Settle() { - return _settle; + return _settle.Timeout(_timeout).Catch(_ => Observable.Empty()); } void IRequestSettler.OnStartRequest() diff --git a/src/JsonRpc/CompositeHandlersManager.cs b/src/JsonRpc/CompositeHandlersManager.cs index c7caa2851..8607afbb4 100644 --- a/src/JsonRpc/CompositeHandlersManager.cs +++ b/src/JsonRpc/CompositeHandlersManager.cs @@ -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; } } diff --git a/src/JsonRpc/HandlerCollection.cs b/src/JsonRpc/HandlerCollection.cs index c5a7c527c..a1f85c147 100644 --- a/src/JsonRpc/HandlerCollection.cs +++ b/src/JsonRpc/HandlerCollection.cs @@ -9,9 +9,11 @@ namespace OmniSharp.Extensions.JsonRpc { + + public class HandlerCollection : IEnumerable, IHandlersManager { - internal readonly List _handlers = new List(); + internal readonly List _handlers = new List(); public HandlerCollection() { } @@ -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 GetEnumerator() { return _handlers.GetEnumerator(); @@ -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) @@ -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<>), diff --git a/src/JsonRpc/IHandlersManager.cs b/src/JsonRpc/IHandlersManager.cs index ce152f4df..506c94740 100644 --- a/src/JsonRpc/IHandlersManager.cs +++ b/src/JsonRpc/IHandlersManager.cs @@ -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); } } diff --git a/src/JsonRpc/JsonRpcOptionsRegistryBase.cs b/src/JsonRpc/JsonRpcOptionsRegistryBase.cs index f3cdf07a0..5ad63eab9 100644 --- a/src/JsonRpc/JsonRpcOptionsRegistryBase.cs +++ b/src/JsonRpc/JsonRpcOptionsRegistryBase.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; namespace OmniSharp.Extensions.JsonRpc @@ -6,6 +7,15 @@ namespace OmniSharp.Extensions.JsonRpc public abstract class JsonRpcOptionsRegistryBase : JsonRpcCommonMethodsBase where T : IJsonRpcHandlerRegistry { 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 diff --git a/src/JsonRpc/JsonRpcServer.cs b/src/JsonRpc/JsonRpcServer.cs index 713278e88..8c51ec63e 100644 --- a/src/JsonRpc/JsonRpcServer.cs +++ b/src/JsonRpc/JsonRpcServer.cs @@ -98,6 +98,7 @@ internal JsonRpcServer(JsonRpcServerOptions options) : base(options) ); _disposable.Add(_connection); _collection.Add(_serviceProvider.GetRequiredService>().ToArray()); + options.AddLinks(_collection); } private async Task Initialize(CancellationToken cancellationToken) diff --git a/src/JsonRpc/JsonRpcServerOptionsBase.cs b/src/JsonRpc/JsonRpcServerOptionsBase.cs index 5e84209b3..0a6686757 100644 --- a/src/JsonRpc/JsonRpcServerOptionsBase.cs +++ b/src/JsonRpc/JsonRpcServerOptionsBase.cs @@ -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; + } } } diff --git a/src/Protocol/AbstractHandlers.cs b/src/Protocol/AbstractHandlers.cs index 5b418cd8c..32e34bdb3 100644 --- a/src/Protocol/AbstractHandlers.cs +++ b/src/Protocol/AbstractHandlers.cs @@ -68,6 +68,8 @@ async Task IRequestHandler.Handle(TItem request, } var subject = new AsyncSubject(); + // in the event nothing is emitted... + subject.OnNext(default); Handle(request, subject, cancellationToken); return _factory(await subject); } diff --git a/src/Protocol/Client/IRegisterCapabilityHandler.cs b/src/Protocol/Client/IRegisterCapabilityHandler.cs index 0afa0b92b..ff0a10b67 100644 --- a/src/Protocol/Client/IRegisterCapabilityHandler.cs +++ b/src/Protocol/Client/IRegisterCapabilityHandler.cs @@ -8,7 +8,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Client { - [Serial, Method(ClientNames.RegisterCapability, Direction.ServerToClient)] + [Parallel, Method(ClientNames.RegisterCapability, Direction.ServerToClient)] [GenerateHandlerMethods, GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer))] public interface IRegisterCapabilityHandler : IJsonRpcRequestHandler { diff --git a/src/Protocol/Client/IUnregisterCapabilityHandler.cs b/src/Protocol/Client/IUnregisterCapabilityHandler.cs index 7354eefd5..ee163eb86 100644 --- a/src/Protocol/Client/IUnregisterCapabilityHandler.cs +++ b/src/Protocol/Client/IUnregisterCapabilityHandler.cs @@ -8,7 +8,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Client { - [Serial, Method(ClientNames.UnregisterCapability, Direction.ServerToClient)] + [Parallel, Method(ClientNames.UnregisterCapability, Direction.ServerToClient)] [GenerateHandlerMethods, GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer))] public interface IUnregisterCapabilityHandler : IJsonRpcRequestHandler { } diff --git a/src/Protocol/Window/ILogMessageHandler.cs b/src/Protocol/Window/ILogMessageHandler.cs index 41509a184..953c9b8b5 100644 --- a/src/Protocol/Window/ILogMessageHandler.cs +++ b/src/Protocol/Window/ILogMessageHandler.cs @@ -19,6 +19,31 @@ public abstract class LogMessageHandler : ILogMessageHandler public static partial class LogMessageExtensions { + public static void Log(this ILanguageServer mediator, LogMessageParams @params) + { + mediator.LogMessage(@params); + } + + public static void LogError(this ILanguageServer mediator, string message) + { + mediator.LogMessage(new LogMessageParams() { Type = MessageType.Error, Message = message }); + } + + public static void Log(this ILanguageServer mediator, string message) + { + mediator.LogMessage(new LogMessageParams() { Type = MessageType.Log, Message = message }); + } + + public static void LogWarning(this ILanguageServer mediator, string message) + { + mediator.LogMessage(new LogMessageParams() { Type = MessageType.Warning, Message = message }); + } + + public static void LogInfo(this ILanguageServer mediator, string message) + { + mediator.LogMessage(new LogMessageParams() { Type = MessageType.Info, Message = message }); + } + public static void Log(this IWindowLanguageServer mediator, LogMessageParams @params) { mediator.LogMessage(@params); diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index 3b9ea995b..df10a6d39 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -31,6 +31,7 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Server.WorkDone; using OmniSharp.Extensions.LanguageServer.Protocol.Shared; +using OmniSharp.Extensions.LanguageServer.Protocol.Window; using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; using OmniSharp.Extensions.LanguageServer.Server.Configuration; using OmniSharp.Extensions.LanguageServer.Server.Logging; @@ -85,7 +86,7 @@ public static LanguageServer PreInit(Action optionsAction public static async Task From(LanguageServerOptions options, CancellationToken token) { - var server = (LanguageServer)PreInit(options); + var server = (LanguageServer) PreInit(options); await server.Initialize(token); return server; @@ -199,6 +200,7 @@ internal LanguageServer(LanguageServerOptions options) : base(options) var serviceIdentifiers = _serviceProvider.GetServices().ToArray(); _disposable.Add(_textDocumentIdentifiers.Add(serviceIdentifiers)); _disposable.Add(_collection.Add(serviceHandlers)); + options.AddLinks(_collection); } } @@ -420,7 +422,7 @@ async Task IRequestHandler OpenClose = _collection.ContainsHandler(typeof(IDidOpenTextDocumentHandler)) || _collection.ContainsHandler(typeof(IDidCloseTextDocumentHandler)), Save = _collection.ContainsHandler(typeof(IDidSaveTextDocumentHandler)) - ? new SaveOptions() { IncludeText = true /* TODO: Make configurable */} + ? new SaveOptions() {IncludeText = true /* TODO: Make configurable */} : null, WillSave = _collection.ContainsHandler(typeof(IWillSaveTextDocumentHandler)), WillSaveWaitUntil = _collection.ContainsHandler(typeof(IWillSaveWaitUntilTextDocumentHandler)) @@ -476,12 +478,23 @@ private async Task DynamicallyRegisterHandlers(Registration[] registrations) if (registrations.Length == 0) return; // No dynamic registrations supported by client. - var @params = new RegistrationParams() { Registrations = registrations }; - await _initializeComplete; - await Client.RegisterCapability(@params); + // Some clients (read: vscode) will throw errors on the first unhandled registration it encounters (and never registers the rest) + // This is not really desirable as if we send a registration they don't support... that shouldn't break any unprocessed registrations + // So in order to fix this we just send each registration along as separate requests all at once. + await registrations + .ToObservable() + .Select(z => Observable.FromAsync(ct => Client.RegisterCapability(new RegistrationParams() {Registrations = new RegistrationContainer(z)}, ct)) + .Catch(_ => { + this.LogWarning($"Unable to dynamically register capability '{z.Method}' perhaps it is not supported?"); + return Observable.Empty(); + }) + ) + .Merge() + .ToTask(); } + public IObservable Start => _initializeComplete.AsObservable(); public Task WasStarted => _initializeComplete.ToTask(); @@ -497,6 +510,7 @@ public void Dispose() protected override IResponseRouter ResponseRouter => _responseRouter; protected override IHandlersManager HandlersManager => _collection; + public IDisposable Register(Action registryAction) { var manager = new CompositeHandlersManager(_collection); @@ -550,16 +564,17 @@ private IDisposable RegisterHandlers(IDisposable handlerDisposable) { return new CompositeDisposable(lsp, RegisterHandlers(lsp.Descriptors)); } + if (!(handlerDisposable is CompositeDisposable cd)) return Disposable.Empty; cd.Add(RegisterHandlers(cd.OfType().SelectMany(z => z.Descriptors))); return cd; } - } class LangaugeServerRegistry : InterimLanguageProtocolRegistry, ILanguageServerRegistry { - public LangaugeServerRegistry(IServiceProvider serviceProvider, CompositeHandlersManager handlersManager, TextDocumentIdentifiers textDocumentIdentifiers) : base(serviceProvider, handlersManager, textDocumentIdentifiers) + public LangaugeServerRegistry(IServiceProvider serviceProvider, CompositeHandlersManager handlersManager, TextDocumentIdentifiers textDocumentIdentifiers) : base( + serviceProvider, handlersManager, textDocumentIdentifiers) { } } diff --git a/src/Shared/SharedHandlerCollection.cs b/src/Shared/SharedHandlerCollection.cs index a583010b5..12c5c5e88 100644 --- a/src/Shared/SharedHandlerCollection.cs +++ b/src/Shared/SharedHandlerCollection.cs @@ -18,6 +18,7 @@ class SharedHandlerCollection : IHandlerCollection private static readonly MethodInfo GetRegistrationMethod = typeof(SharedHandlerCollection) .GetTypeInfo() .GetMethod(nameof(GetRegistration), BindingFlags.NonPublic | BindingFlags.Static); + private readonly ISupportedCapabilities _supportedCapabilities; private readonly TextDocumentIdentifiers _textDocumentIdentifiers; internal readonly HashSet _handlers = new HashSet(); @@ -45,10 +46,26 @@ IEnumerator IEnumerable.GetEnumerator() return GetEnumerator(); } - IDisposable IHandlersManager.Add(IJsonRpcHandler handler, JsonRpcHandlerOptions options) => Add( new [] { handler }, options); + IDisposable IHandlersManager.Add(IJsonRpcHandler handler, JsonRpcHandlerOptions options) => Add(new[] {handler}, options); IDisposable IHandlersManager.Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOptions options) => Add(method, handler, options); + IDisposable IHandlersManager.AddLink(string sourceMethod, string destinationMethod) + { + var source = _handlers.First(z => z.Method == sourceMethod); + LspHandlerDescriptor descriptor = null; + descriptor = GetDescriptor(destinationMethod, source.HandlerType, source.Handler, + source.RequestProcessType.HasValue ? new JsonRpcHandlerOptions() {RequestProcessType = source.RequestProcessType.Value} : null); + _handlers.Add(descriptor); + var cd = new CompositeDisposable(); + if (descriptor.Handler is ITextDocumentIdentifier textDocumentIdentifier) + { + cd.Add(_textDocumentIdentifiers.Add(textDocumentIdentifier)); + } + + return new LspHandlerDescriptorDisposable(new[] {descriptor}, cd); + } + public LspHandlerDescriptorDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOptions options) { var descriptor = GetDescriptor(method, handler.GetType(), handler, options); @@ -58,7 +75,8 @@ public LspHandlerDescriptorDisposable Add(string method, IJsonRpcHandler handler { cd.Add(_textDocumentIdentifiers.Add(textDocumentIdentifier)); } - return new LspHandlerDescriptorDisposable(new[] { descriptor }, cd); + + return new LspHandlerDescriptorDisposable(new[] {descriptor}, cd); } public LspHandlerDescriptorDisposable Add(string method, Func handlerFunc, JsonRpcHandlerOptions options) @@ -71,7 +89,8 @@ public LspHandlerDescriptorDisposable Add(string method, Func), handlerType); - var capabilityType = typeDescriptor?.CapabilityType ?? HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handlerType); + var registrationType = typeDescriptor?.RegistrationType ?? + HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handlerType) ?? + HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handler.GetType()); + var capabilityType = typeDescriptor?.CapabilityType ?? + HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handlerType) ?? + HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handler.GetType()); Type @params = null; object registrationOptions = null; @@ -189,7 +213,7 @@ private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJso { registrationOptions = GetRegistrationMethod .MakeGenericMethod(registrationType) - .Invoke(null, new object[] { handler }); + .Invoke(null, new object[] {handler}); } var key = "default"; @@ -200,10 +224,12 @@ private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJso { key = handlerRegistration?.GetRegistrationOptions()?.DocumentSelector ?? key; } + // In some scenarios, users will implement both the main handler and the resolve handler to the same class // This allows us to get a key for those interfaces so we can register many resolve handlers // and then route those resolve requests to the correct handler - if (handler.GetType().GetTypeInfo().ImplementedInterfaces.Any(x => x.GetTypeInfo().IsGenericType && x.GetTypeInfo().GetGenericTypeDefinition() == typeof(ICanBeResolvedHandler<>))) + if (handler.GetType().GetTypeInfo().ImplementedInterfaces + .Any(x => x.GetTypeInfo().IsGenericType && x.GetTypeInfo().GetGenericTypeDefinition() == typeof(ICanBeResolvedHandler<>))) { key = handlerRegistration?.GetRegistrationOptions()?.DocumentSelector ?? key; } @@ -214,10 +240,10 @@ private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJso var requestProcessType = options?.RequestProcessType ?? typeDescriptor?.RequestProcessType ?? - handlerType.GetCustomAttributes(true) - .Concat(@interface.GetCustomAttributes(true)) - .OfType() - .FirstOrDefault()?.Type; + handlerType.GetCustomAttributes(true) + .Concat(@interface.GetCustomAttributes(true)) + .OfType() + .FirstOrDefault()?.Type; var descriptor = new LspHandlerDescriptor( method, @@ -227,12 +253,10 @@ private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJso @params, registrationType, registrationOptions, - (registrationType == null ? (Func) (() => false) : (() => _supportedCapabilities.AllowsDynamicRegistration(capabilityType))), + (registrationType == null ? (Func) (() => false) : (() => _supportedCapabilities.AllowsDynamicRegistration(capabilityType))), capabilityType, requestProcessType, - () => { - _handlers.RemoveWhere(d => d.Handler == handler); - }); + () => { _handlers.RemoveWhere(d => d.Handler == handler); }); return descriptor; } diff --git a/test/JsonRpc.Tests/IntegrationTests.cs b/test/JsonRpc.Tests/IntegrationTests.cs index 1014bcb02..31e82b897 100644 --- a/test/JsonRpc.Tests/IntegrationTests.cs +++ b/test/JsonRpc.Tests/IntegrationTests.cs @@ -179,5 +179,30 @@ public async Task Should_Cancel_Parallel_Requests_When_Options_Are_Given() await action.Should().ThrowAsync(); } } + + [Fact] + public async Task Should_Link_Request_A_to_Request_B() + { + var (client, server) = await Initialize( + client => { + client + .OnRequest("myrequest", async () => new Data() {Value = "myresponse"}) + .WithLink("myrequest", "myrequest2") + ; + }, + server => { + server + .OnRequest("myrequest", async () => new Data() {Value = string.Join("", "myresponse".Reverse())}) + .WithLink("myrequest", "myrequest2") + ; + } + ); + + var serverResponse = await client.SendRequest("myrequest2").Returning(CancellationToken); + serverResponse.Value.Should().Be("esnopserym"); + + var clientResponse = await server.SendRequest("myrequest2").Returning(CancellationToken); + clientResponse.Value.Should().Be("myresponse"); + } } } diff --git a/test/JsonRpc.Tests/Server/SpecifictionIdTests.cs b/test/JsonRpc.Tests/Server/SpecificatiosIdTests.cs similarity index 98% rename from test/JsonRpc.Tests/Server/SpecifictionIdTests.cs rename to test/JsonRpc.Tests/Server/SpecificatiosIdTests.cs index 14bb27ae0..f139f8f4b 100644 --- a/test/JsonRpc.Tests/Server/SpecifictionIdTests.cs +++ b/test/JsonRpc.Tests/Server/SpecificatiosIdTests.cs @@ -12,7 +12,7 @@ namespace JsonRpc.Tests.Server { - public class SpecifictionIdTests + public class SpecificatiosIdTests { [Theory] [ClassData(typeof(SimpleTestMessages))] diff --git a/test/JsonRpc.Tests/Server/SpecifictionRecieverTests.cs b/test/JsonRpc.Tests/Server/SpecifictionRecieverTests.cs index 80429cdaf..306566733 100644 --- a/test/JsonRpc.Tests/Server/SpecifictionRecieverTests.cs +++ b/test/JsonRpc.Tests/Server/SpecifictionRecieverTests.cs @@ -9,7 +9,7 @@ namespace JsonRpc.Tests.Server { - public class SpecifictionReceiverTests + public class SpecificationReceiverTests { [Theory] [ClassData(typeof(SpecificationMessages))] diff --git a/test/Lsp.Tests/Integration/ConnectionAndDisconnectionTests.cs b/test/Lsp.Tests/Integration/ConnectionAndDisconnectionTests.cs index 4bf70598d..76e45fe60 100644 --- a/test/Lsp.Tests/Integration/ConnectionAndDisconnectionTests.cs +++ b/test/Lsp.Tests/Integration/ConnectionAndDisconnectionTests.cs @@ -53,9 +53,41 @@ public async Task Client_Should_Stay_Alive_When_Requests_Throw_An_Exception() result.Should().BeTrue(); } + [Fact] + public async Task Server_Should_Support_Links() + { + var (client, server) = await Initialize(ConfigureClient, ConfigureServer); + + var result = await client.SendRequest("ka").Returning(CancellationToken); + result.Should().BeTrue(); + + Func a = () => client.SendRequest("t").ReturningVoid(CancellationToken); + await a.Should().ThrowAsync(); + + result = await client.SendRequest("ka").Returning(CancellationToken); + result.Should().BeTrue(); + } + + [Fact] + public async Task Client_Should_Support_Links() + { + var (client, server) = await Initialize(ConfigureClient, ConfigureServer); + + var result = await server.SendRequest("ka").Returning(CancellationToken); + result.Should().BeTrue(); + + Func a = () => server.SendRequest("t").ReturningVoid(CancellationToken); + await a.Should().ThrowAsync(); + + result = await server.SendRequest("ka").Returning(CancellationToken); + result.Should().BeTrue(); + } + private void ConfigureClient(LanguageClientOptions options) { options.OnRequest("keepalive", (ct) => Task.FromResult(true)); + options.WithLink("keepalive", "ka"); + options.WithLink("throw", "t"); options.OnRequest("throw", async ct => { throw new NotSupportedException(); return Task.CompletedTask; @@ -65,6 +97,8 @@ private void ConfigureClient(LanguageClientOptions options) private void ConfigureServer(LanguageServerOptions options) { options.OnRequest("keepalive", (ct) => Task.FromResult(true)); + options.WithLink("keepalive", "ka"); + options.WithLink("throw", "t"); options.OnRequest("throw", async ct => { throw new NotSupportedException(); return Task.CompletedTask; diff --git a/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs b/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs index e7a6f11dc..bc5eae7b1 100644 --- a/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs +++ b/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Reactive.Linq; +using System.Reactive.Threading.Tasks; using System.Threading.Tasks; using FluentAssertions; using NSubstitute; @@ -34,10 +35,7 @@ public async Task Should_Register_Dynamically_After_Initialization() client.ServerSettings.Capabilities.CompletionProvider.Should().BeNull(); - await Events.SettleNext(); - await Events.SettleNext(); - await Events.SettleNext(); - await Events.SettleNext(); + await Events.Settle().Take(2); client.RegistrationManager.CurrentRegistrations.Should().Contain(x => x.Method == TextDocumentNames.Completion && SelectorMatches(x, z=> z.HasLanguage && z.Language == "csharp") @@ -51,7 +49,7 @@ public async Task Should_Register_Dynamically_While_Server_Is_Running() client.ServerSettings.Capabilities.CompletionProvider.Should().BeNull(); - await Events.SettleNext(); + await SettleNext(); server.Register(x => x .OnCompletion( @@ -61,13 +59,52 @@ public async Task Should_Register_Dynamically_While_Server_Is_Running() }) ); - await Task.Delay(TimeSpan.FromSeconds(1)); + await SettleNext(); client.RegistrationManager.CurrentRegistrations.Should().Contain(x => x.Method == TextDocumentNames.Completion && SelectorMatches(x, z=> z.HasLanguage && z.Language == "vb") ); } + [Fact] + public async Task Should_Register_Links_Dynamically_While_Server_Is_Running() + { + var (client, server) = await Initialize(ConfigureClient, ConfigureServer); + + client.ServerSettings.Capabilities.CompletionProvider.Should().BeNull(); + + await SettleNext(); + + server.Register(x => x + .OnCompletion( + (@params, token) => Task.FromResult(new CompletionList()), + registrationOptions: new CompletionRegistrationOptions() { + DocumentSelector = DocumentSelector.ForLanguage("vb") + }) + ); + + await SettleNext(); + + client.RegistrationManager.CurrentRegistrations.Should().Contain(x => + x.Method == TextDocumentNames.Completion && SelectorMatches(x, z=> z.HasLanguage && z.Language == "vb") + ); + } + + [Fact] + public async Task Should_Gather_Linked_Registrations() + { + var (client, server) = await Initialize(ConfigureClient, + options => { + ConfigureServer(options); + options.WithLink(TextDocumentNames.SemanticTokensFull, "@/" + TextDocumentNames.SemanticTokensFull); + }); + + await Events.Settle().Take(2); + + client.RegistrationManager.CurrentRegistrations.Should().Contain(x => x.Method == TextDocumentNames.SemanticTokensFull); + client.RegistrationManager.CurrentRegistrations.Should().Contain(x => x.Method == "@/" + TextDocumentNames.SemanticTokensFull); + } + [Fact] public async Task Should_Unregister_Dynamically_While_Server_Is_Running() { @@ -88,7 +125,7 @@ public async Task Should_Unregister_Dynamically_While_Server_Is_Running() disposable.Dispose(); - await Task.Delay(TimeSpan.FromSeconds(1)); + await Events.Settle(); client.RegistrationManager.CurrentRegistrations.Should().NotContain(x => x.Method == TextDocumentNames.Completion && SelectorMatches(x, z=> z.HasLanguage && z.Language == "vb") diff --git a/test/Lsp.Tests/Integration/PartialItemTests.cs b/test/Lsp.Tests/Integration/PartialItemTests.cs index 982131af0..cb90cf8f8 100644 --- a/test/Lsp.Tests/Integration/PartialItemTests.cs +++ b/test/Lsp.Tests/Integration/PartialItemTests.cs @@ -70,7 +70,7 @@ public async Task Should_Behave_Like_An_Observable_With_WorkDone() Observer.Create(z => work.Add(z)) ).Subscribe(x => items.AddRange(x)); - await SettleNext(); + await Task.Delay(1000); var workResults = work.Select(z => z.Message); diff --git a/vscode-testextension/package-lock.json b/vscode-testextension/package-lock.json index 31d0affdc..19e56b8b7 100644 --- a/vscode-testextension/package-lock.json +++ b/vscode-testextension/package-lock.json @@ -4,87 +4,39 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, "@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.0.0.tgz", + "integrity": "sha512-jWeYcTo3sCH/rMgsdYXDTO85GNRyTCII5dayMIu/ZO4zbEot1E3iNGaOwpLReLUHjeNQFkgeNNVYlY4dX6azQQ==", "dev": true }, "@types/node": { - "version": "13.11.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz", - "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==", + "version": "14.0.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.24.tgz", + "integrity": "sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA==", "dev": true }, "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", + "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "debug": "4" } }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -107,21 +59,6 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, "commander": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", @@ -134,52 +71,21 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", @@ -201,66 +107,16 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -277,22 +133,6 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dev": true, - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -306,34 +146,24 @@ "dev": true }, "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "dev": true, "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" } }, "https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "dev": true, "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" + "agent-base": "6", + "debug": "4" } }, "inflight": { @@ -352,69 +182,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", - "dev": true - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true, - "requires": { - "mime-db": "1.40.0" - } - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -458,6 +225,15 @@ "supports-color": "5.4.0" }, "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -471,19 +247,19 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "once": { @@ -501,82 +277,6 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "psl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", - "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", - "dev": true - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -590,32 +290,15 @@ "dev": true }, "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", @@ -625,108 +308,39 @@ "has-flag": "^3.0.0" } }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vscode": { - "version": "1.1.36", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.36.tgz", - "integrity": "sha512-cGFh9jmGLcTapCpPCKvn8aG/j9zVQ+0x5hzYJq5h5YyUXVGa1iamOaB2M2PZXoumQPES4qeAP1FwkI0b6tL4bQ==", + "version": "1.1.37", + "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.37.tgz", + "integrity": "sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg==", "dev": true, "requires": { "glob": "^7.1.2", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", "mocha": "^5.2.0", - "request": "^2.88.0", "semver": "^5.4.1", "source-map-support": "^0.5.0", - "url-parse": "^1.4.4", "vscode-test": "^0.4.1" } }, "vscode-jsonrpc": { - "version": "5.1.0-next.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.1.0-next.1.tgz", - "integrity": "sha512-mwLDojZkbmpizSJSmp690oa9FB9jig18SIDGZeBCvFc2/LYSRvMm/WwWtMBJuJ1MfFh7rZXfQige4Uje5Z9NzA==" + "version": "6.0.0-next.3", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.3.tgz", + "integrity": "sha512-bkAtRMXbTwU1pAXnlbkAMnrqXZX3q2/zttkcnPZOsDqgoycO2L7GK2aN3K5qCMZmhItwBU185T78Q9YH0v5jEA==" }, "vscode-languageclient": { - "version": "6.2.0-next.2", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.2.0-next.2.tgz", - "integrity": "sha512-RqOrj+OCZmiMcLgmQSx581O+3rHb/AIFpEL+yoBcqFkqfIwMkoowCChEJGwVe/I8FeEphZ4dzlMm0MPW+p/DNA==", + "version": "7.0.0-next.7", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0-next.7.tgz", + "integrity": "sha512-D6CuCDDiwcTyg6EI5E7k7FQZHjfkXpjsI67Am+o89sxPr/1Owrp3246crnD4EHGgp+xx+9u/fuibwRtw9PWJVw==", "requires": { "semver": "^6.3.0", - "vscode-languageserver-protocol": "3.16.0-next.2" + "vscode-languageserver-protocol": "3.16.0-next.5" }, "dependencies": { "semver": { @@ -737,18 +351,18 @@ } }, "vscode-languageserver-protocol": { - "version": "3.16.0-next.2", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.2.tgz", - "integrity": "sha512-atmkGT/W6tF0cx4SaWFYtFs2UeSeC28RPiap9myv2YZTaTCFvTBEPNWrU5QRKfkyM0tbgtGo6T3UCQ8tkDpjzA==", + "version": "3.16.0-next.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.5.tgz", + "integrity": "sha512-MVuLT4d5tdDo/14laViyZY+p1HT7wYDwJdvGmo8mCfkgON5c10AABhtqjD+LccidBcwdbKy+4dwwUUxiNg/8PA==", "requires": { - "vscode-jsonrpc": "5.1.0-next.1", - "vscode-languageserver-types": "3.16.0-next.1" + "vscode-jsonrpc": "6.0.0-next.3", + "vscode-languageserver-types": "3.16.0-next.2" } }, "vscode-languageserver-types": { - "version": "3.16.0-next.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.1.tgz", - "integrity": "sha512-tZFUSbyjUcrh+qQf13ALX4QDdOfDX0cVaBFgy7ktJ0VwS7AW/yRKgGPSxVqqP9OCMNPdqP57O5q47w2pEwfaUg==" + "version": "3.16.0-next.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz", + "integrity": "sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==" }, "vscode-test": { "version": "0.4.3", @@ -758,6 +372,52 @@ "requires": { "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "wrappy": { diff --git a/vscode-testextension/package.json b/vscode-testextension/package.json index 54f74bcff..0eea6966c 100644 --- a/vscode-testextension/package.json +++ b/vscode-testextension/package.json @@ -46,12 +46,12 @@ "postinstall": "node ./node_modules/vscode/bin/install" }, "devDependencies": { - "@types/mocha": "^7.0.2", - "@types/node": "^13.11.1", - "typescript": "^3.8.3", - "vscode": "^1.1.36" + "@types/mocha": "^8.0.0", + "@types/node": "^14.0.24", + "typescript": "^3.9.7", + "vscode": "^1.1.37" }, "dependencies": { - "vscode-languageclient": "^6.2.0-next.2" + "vscode-languageclient": "^7.0.0-next.7" } } diff --git a/vscode-testextension/src/extension.ts b/vscode-testextension/src/extension.ts index f69bf2a33..722980405 100644 --- a/vscode-testextension/src/extension.ts +++ b/vscode-testextension/src/extension.ts @@ -17,8 +17,8 @@ import { InitializeParams, StreamInfo, createServerPipeTransport, -} from "vscode-languageclient"; -import { Trace, createClientPipeTransport } from "vscode-jsonrpc"; +} from "vscode-languageclient/node"; +import { Trace, createClientPipeTransport } from "vscode-jsonrpc/node"; import { createConnection } from "net"; export function activate(context: ExtensionContext) { From 153ec240390b9d8c46be8959cf4ebf2c525e51c0 Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Thu, 23 Jul 2020 00:00:17 -0400 Subject: [PATCH 03/10] fixed Trace property --- src/Client/LanguageClient.cs | 2 +- src/Protocol/Models/InitializeParams.cs | 2 +- src/Server/LanguageServer.cs | 2 +- test/Lsp.Tests/Models/InitializeParamsTests.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Client/LanguageClient.cs b/src/Client/LanguageClient.cs index faa999ae9..d2eaddd29 100644 --- a/src/Client/LanguageClient.cs +++ b/src/Client/LanguageClient.cs @@ -221,7 +221,7 @@ internal LanguageClient(LanguageClientOptions options) : base(options) public async Task Initialize(CancellationToken token) { var @params = new InitializeParams { - TraceValue = _traceValue, + Trace = _traceValue, Capabilities = _clientCapabilities, ClientInfo = _clientInfo, RootUri = _rootUri, diff --git a/src/Protocol/Models/InitializeParams.cs b/src/Protocol/Models/InitializeParams.cs index 1a8009ec9..d1d050143 100644 --- a/src/Protocol/Models/InitializeParams.cs +++ b/src/Protocol/Models/InitializeParams.cs @@ -57,7 +57,7 @@ public string RootPath /// The initial trace setting. If omitted trace is disabled ('off'). /// [Optional] - public TraceValue TraceValue { get; set; } = TraceValue.Off; + public TraceValue Trace { get; set; } = TraceValue.Off; /// /// The workspace folders configured in the client when the server starts. diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index df10a6d39..ae2494a46 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -269,7 +269,7 @@ async Task IRequestHandler { ClientSettings = request; - if (request.TraceValue == TraceValue.Verbose) + if (request.Trace == TraceValue.Verbose) { var loggerSettings = _serviceProvider.GetService(); diff --git a/test/Lsp.Tests/Models/InitializeParamsTests.cs b/test/Lsp.Tests/Models/InitializeParamsTests.cs index 4531dd105..8890d074a 100644 --- a/test/Lsp.Tests/Models/InitializeParamsTests.cs +++ b/test/Lsp.Tests/Models/InitializeParamsTests.cs @@ -75,7 +75,7 @@ public void SimpleTest(string expected) InitializationOptions = null, ProcessId = 1234, RootUri = new Uri("file:///file/abc/12.cs"), - TraceValue = TraceValue.Verbose + Trace = TraceValue.Verbose }; var result = Fixture.SerializeObject(model); From fdd33e2b1bb8b5ad2224b49ae8b2ce0d84b8c5b9 Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Thu, 23 Jul 2020 01:07:01 -0400 Subject: [PATCH 04/10] Added method that takes in a range to be similar to the vscode api, however watch for allocations --- .../Proposals/SemanticTokensBuilder.cs | 117 ++++++++++++++++-- test/Lsp.Tests/SemanticTokensDocumentTests.cs | 54 +++++++- 2 files changed, 158 insertions(+), 13 deletions(-) diff --git a/src/Protocol/Document/Proposals/SemanticTokensBuilder.cs b/src/Protocol/Document/Proposals/SemanticTokensBuilder.cs index 8797dcc9c..0679dca35 100644 --- a/src/Protocol/Document/Proposals/SemanticTokensBuilder.cs +++ b/src/Protocol/Document/Proposals/SemanticTokensBuilder.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals { @@ -29,32 +30,115 @@ public SemanticTokensBuilder( _data = ImmutableArray.Empty.ToBuilder(); } - public void Push(int line, int @char, int length, SemanticTokenType? tokenType, - params SemanticTokenModifier[] tokenModifiers) + /// + /// Push a token onto the builder + /// + /// + /// + /// + /// + /// + public void Push(int line, int @char, int length, SemanticTokenType? tokenType, params SemanticTokenModifier[] tokenModifiers) { - Push(line, @char, length, _legend.GetTokenTypeIdentity(tokenType), - _legend.GetTokenModifiersIdentity(tokenModifiers)); + Push(line, @char, length, _legend.GetTokenTypeIdentity(tokenType), _legend.GetTokenModifiersIdentity(tokenModifiers)); } - public void Push(int line, int @char, int length, SemanticTokenType? tokenType, - IEnumerable tokenModifiers) + /// + /// Push a token onto the builder + /// + /// Avoid creating the range just to call this method + /// The range, cannot span multiple lines + /// + /// + public void Push(Range range, SemanticTokenType? tokenType, params SemanticTokenModifier[] tokenModifiers) { - Push(line, @char, length, _legend.GetTokenTypeIdentity(tokenType), - _legend.GetTokenModifiersIdentity(tokenModifiers)); + Push(range, _legend.GetTokenTypeIdentity(tokenType), _legend.GetTokenModifiersIdentity(tokenModifiers)); } + /// + /// Push a token onto the builder + /// + /// + /// + /// + /// + /// + public void Push(int line, int @char, int length, SemanticTokenType? tokenType, IEnumerable tokenModifiers) + { + Push(line, @char, length, _legend.GetTokenTypeIdentity(tokenType), _legend.GetTokenModifiersIdentity(tokenModifiers)); + } + + /// + /// Push a token onto the builder + /// + /// Avoid creating the range just to call this method + /// The range, cannot span multiple lines + /// + /// + public void Push(Range range, SemanticTokenType? tokenType, IEnumerable tokenModifiers) + { + Push(range, _legend.GetTokenTypeIdentity(tokenType), _legend.GetTokenModifiersIdentity(tokenModifiers)); + } + + /// + /// Push a token onto the builder + /// + /// + /// + /// + /// + /// public void Push(int line, int @char, int length, string tokenType, params string[] tokenModifiers) { - Push(line, @char, length, _legend.GetTokenTypeIdentity(tokenType), - _legend.GetTokenModifiersIdentity(tokenModifiers)); + Push(line, @char, length, _legend.GetTokenTypeIdentity(tokenType), _legend.GetTokenModifiersIdentity(tokenModifiers)); + } + + /// + /// Push a token onto the builder + /// + /// Avoid creating the range just to call this method + /// The range, cannot span multiple lines + /// + /// + public void Push(Range range, string tokenType, params string[] tokenModifiers) + { + Push(range, _legend.GetTokenTypeIdentity(tokenType), _legend.GetTokenModifiersIdentity(tokenModifiers)); } + /// + /// Push a token onto the builder + /// + /// + /// + /// + /// + /// public void Push(int line, int @char, int length, string tokenType, IEnumerable tokenModifiers) { Push(line, @char, length, _legend.GetTokenTypeIdentity(tokenType), _legend.GetTokenModifiersIdentity(tokenModifiers)); } + /// + /// Push a token onto the builder + /// + /// Avoid creating the range just to call this method + /// The range, cannot span multiple lines + /// + /// + public void Push(Range range, string tokenType, IEnumerable tokenModifiers) + { + Push(range, _legend.GetTokenTypeIdentity(tokenType), _legend.GetTokenModifiersIdentity(tokenModifiers)); + } + + /// + /// Push a token onto the builder + /// + /// + /// + /// + /// + /// public void Push(int line, int @char, int length, int tokenType, int tokenModifiers) { var pushLine = line; @@ -75,6 +159,19 @@ public void Push(int line, int @char, int length, int tokenType, int tokenModifi _prevChar = @char; } + /// + /// Push a token onto the builder + /// + /// Avoid creating the range just to call this method + /// The range, cannot span multiple lines + /// + /// + public void Push(Range range, int tokenType, int tokenModifiers) + { + if (range.Start.Line != range.End.Line) throw new ArgumentOutOfRangeException(nameof(range), "Range must not span multiple lines"); + Push(range.Start.Line, range.Start.Character, range.End.Character - range.Start.Character, tokenType, tokenModifiers); + } + /// /// Apply the changes to the source document /// diff --git a/test/Lsp.Tests/SemanticTokensDocumentTests.cs b/test/Lsp.Tests/SemanticTokensDocumentTests.cs index 54b2cb13f..3d3cffd35 100644 --- a/test/Lsp.Tests/SemanticTokensDocumentTests.cs +++ b/test/Lsp.Tests/SemanticTokensDocumentTests.cs @@ -32,8 +32,48 @@ public SemanticTokensDocumentTests(ITestOutputHelper testOutputHelper) _loggerFactory = new TestLoggerFactory(testOutputHelper); _logger = _loggerFactory.CreateLogger(); _legend = new SemanticTokensLegend() { - TokenModifiers = SemanticTokenModifier.Defaults.Select(x => x.ToString()).ToArray(), - TokenTypes = SemanticTokenType.Defaults.Select(x => x.ToString()).ToArray(), + // specify a specific set so that additions to the default list do not cause breaks in the tests. + TokenModifiers = new[] { + new SemanticTokenModifier("documentation"), + new SemanticTokenModifier("declaration"), + new SemanticTokenModifier("definition"), + new SemanticTokenModifier("static"), + new SemanticTokenModifier("async"), + new SemanticTokenModifier("abstract"), + new SemanticTokenModifier("deprecated"), + new SemanticTokenModifier("readonly"), + new SemanticTokenModifier("modification"), + new SemanticTokenModifier("defaultLibrary") + } + .Select(z => z.ToString()) + .ToArray(), + TokenTypes = new[] { + new SemanticTokenType("comment"), + new SemanticTokenType("keyword"), + new SemanticTokenType("string"), + new SemanticTokenType("number"), + new SemanticTokenType("regexp"), + new SemanticTokenType("operator"), + new SemanticTokenType("namespace"), + new SemanticTokenType("type"), + new SemanticTokenType("struct"), + new SemanticTokenType("class"), + new SemanticTokenType("interface"), + new SemanticTokenType("enum"), + new SemanticTokenType("typeParameter"), + new SemanticTokenType("function"), + new SemanticTokenType("member"), + new SemanticTokenType("property"), + new SemanticTokenType("macro"), + new SemanticTokenType("variable"), + new SemanticTokenType("parameter"), + new SemanticTokenType("label"), + new SemanticTokenType("modifier"), + new SemanticTokenType("event"), + new SemanticTokenType("enumMember"), + } + .Select(x => x.ToString()) + .ToArray(), }; } @@ -240,7 +280,15 @@ private void Tokenize(string document, SemanticTokensBuilder builder) index = text.IndexOf(part, index, StringComparison.Ordinal); // _logger.LogDebug("Index for part after {Index}: {Text}", index, part); var item = faker.Generate(); - builder.Push(line, index, part.Length, item.type, item.Modifiers); + if (index % 2 == 0) + { + builder.Push(line, index, part.Length, item.type, item.Modifiers); + } + else + { + // ensure range gets some love + builder.Push(((line, index), (line, part.Length + index)), item.type, item.Modifiers); + } } } } From 96147116c94b2567f20166f629f89202afcf4382 Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Thu, 23 Jul 2020 19:33:38 -0400 Subject: [PATCH 05/10] fixed back tracevalue --- test/Lsp.Tests/Models/InitializeParamsTests_$SimpleTest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Lsp.Tests/Models/InitializeParamsTests_$SimpleTest.json b/test/Lsp.Tests/Models/InitializeParamsTests_$SimpleTest.json index 0892168b7..fa3f3c4d5 100644 --- a/test/Lsp.Tests/Models/InitializeParamsTests_$SimpleTest.json +++ b/test/Lsp.Tests/Models/InitializeParamsTests_$SimpleTest.json @@ -92,6 +92,6 @@ "abc": "test" } }, - "traceValue": "verbose", + "trace": "verbose", "workspaceFolders": null } From 4ee5be06b8ab15a9be1b6da8be9d33f5b7a53eb4 Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Thu, 23 Jul 2020 19:47:08 -0400 Subject: [PATCH 06/10] rollback initialze trace change... will do it later --- src/Client/LanguageClient.cs | 6 +++--- src/Client/LanguageClientOptions.cs | 2 +- src/Client/LanguageClientOptionsExtensions.cs | 4 ++-- src/Protocol/Models/InitializeParams.cs | 2 +- src/Protocol/Models/{TraceValue.cs => InitializeTrace.cs} | 2 +- src/Protocol/Models/SetTraceParams.cs | 2 +- src/Server/LanguageServer.cs | 2 +- test/Lsp.Tests/Models/InitializeParamsTests.cs | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) rename src/Protocol/Models/{TraceValue.cs => InitializeTrace.cs} (92%) diff --git a/src/Client/LanguageClient.cs b/src/Client/LanguageClient.cs index d2eaddd29..292a10ccc 100644 --- a/src/Client/LanguageClient.cs +++ b/src/Client/LanguageClient.cs @@ -48,7 +48,7 @@ public class LanguageClient : JsonRpcServerBase, ILanguageClient private readonly object _initializationOptions; private readonly IWorkspaceFoldersManager _workspaceFoldersManager; private readonly DocumentUri _rootUri; - private readonly TraceValue _traceValue; + private readonly InitializeTrace _trace; private readonly IRegistrationManager _registrationManager; private readonly ClientCapabilities _clientCapabilities; private readonly IProgressManager _progressManager; @@ -121,7 +121,7 @@ internal LanguageClient(LanguageClientOptions options) : base(options) // _initializedDelegates = initializedDelegates; _startedDelegates = options.StartedDelegates; _rootUri = options.RootUri; - _traceValue = options.TraceValue; + _trace = options.Trace; _initializationOptions = options.InitializationOptions; services.AddSingleton(_ => @@ -221,7 +221,7 @@ internal LanguageClient(LanguageClientOptions options) : base(options) public async Task Initialize(CancellationToken token) { var @params = new InitializeParams { - Trace = _traceValue, + Trace = _trace, Capabilities = _clientCapabilities, ClientInfo = _clientInfo, RootUri = _rootUri, diff --git a/src/Client/LanguageClientOptions.cs b/src/Client/LanguageClientOptions.cs index a73a31ff0..33db58c91 100644 --- a/src/Client/LanguageClientOptions.cs +++ b/src/Client/LanguageClientOptions.cs @@ -44,7 +44,7 @@ public string RootPath set => RootUri = DocumentUri.FromFileSystemPath(value); } - public TraceValue TraceValue { get; set; } + public InitializeTrace Trace { get; set; } public object InitializationOptions { get; set; } diff --git a/src/Client/LanguageClientOptionsExtensions.cs b/src/Client/LanguageClientOptionsExtensions.cs index 006e532f0..024e7713f 100644 --- a/src/Client/LanguageClientOptionsExtensions.cs +++ b/src/Client/LanguageClientOptionsExtensions.cs @@ -56,9 +56,9 @@ public static LanguageClientOptions WithRootPath(this LanguageClientOptions opti return options; } - public static LanguageClientOptions WithTrace(this LanguageClientOptions options, TraceValue traceValue) + public static LanguageClientOptions WithTrace(this LanguageClientOptions options, InitializeTrace trace) { - options.TraceValue = traceValue; + options.Trace = trace; return options; } diff --git a/src/Protocol/Models/InitializeParams.cs b/src/Protocol/Models/InitializeParams.cs index d1d050143..9f0c595d1 100644 --- a/src/Protocol/Models/InitializeParams.cs +++ b/src/Protocol/Models/InitializeParams.cs @@ -57,7 +57,7 @@ public string RootPath /// The initial trace setting. If omitted trace is disabled ('off'). /// [Optional] - public TraceValue Trace { get; set; } = TraceValue.Off; + public InitializeTrace Trace { get; set; } = InitializeTrace.Off; /// /// The workspace folders configured in the client when the server starts. diff --git a/src/Protocol/Models/TraceValue.cs b/src/Protocol/Models/InitializeTrace.cs similarity index 92% rename from src/Protocol/Models/TraceValue.cs rename to src/Protocol/Models/InitializeTrace.cs index 243396c6a..d9d55d723 100644 --- a/src/Protocol/Models/TraceValue.cs +++ b/src/Protocol/Models/InitializeTrace.cs @@ -5,7 +5,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models { [JsonConverter(typeof(StringEnumConverter))] - public enum TraceValue + public enum InitializeTrace { [EnumMember(Value="off")] Off, diff --git a/src/Protocol/Models/SetTraceParams.cs b/src/Protocol/Models/SetTraceParams.cs index 4dcdd9911..2b3ddceb7 100644 --- a/src/Protocol/Models/SetTraceParams.cs +++ b/src/Protocol/Models/SetTraceParams.cs @@ -9,6 +9,6 @@ public class SetTraceParams : IRequest /// /// The new value that should be assigned to the trace setting. /// - public TraceValue Value { get; set; } + public InitializeTrace Value { get; set; } } } diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index ae2494a46..b16df060b 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -269,7 +269,7 @@ async Task IRequestHandler { ClientSettings = request; - if (request.Trace == TraceValue.Verbose) + if (request.Trace == InitializeTrace.Verbose) { var loggerSettings = _serviceProvider.GetService(); diff --git a/test/Lsp.Tests/Models/InitializeParamsTests.cs b/test/Lsp.Tests/Models/InitializeParamsTests.cs index 8890d074a..2a7e23eac 100644 --- a/test/Lsp.Tests/Models/InitializeParamsTests.cs +++ b/test/Lsp.Tests/Models/InitializeParamsTests.cs @@ -75,7 +75,7 @@ public void SimpleTest(string expected) InitializationOptions = null, ProcessId = 1234, RootUri = new Uri("file:///file/abc/12.cs"), - Trace = TraceValue.Verbose + Trace = InitializeTrace.Verbose }; var result = Fixture.SerializeObject(model); From 42a0a63f06fae6d9920ac6747593421deddbcfd6 Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Thu, 23 Jul 2020 21:26:16 -0400 Subject: [PATCH 07/10] Fixed an issue with registration for semantic tokens --- sample/SampleServer/Program.cs | 3 - .../Proposals/ISemanticTokensDeltaHandler.cs | 4 +- src/Protocol/IRegistration.cs | 8 + src/Protocol/Shared/LspHandlerDescriptor.cs | 5 +- src/Server/LanguageServer.cs | 5 + src/Shared/SharedHandlerCollection.cs | 45 +- .../Integration/DynamicRegistrationTests.cs | 2 + .../ExecuteCommandHandlerMatcherTests.cs | 3 +- .../Matchers/ResolveCommandMatcherTests.cs | 42 +- vscode-testextension/package-lock.json | 830 +++++++++--------- vscode-testextension/package.json | 5 +- 11 files changed, 506 insertions(+), 446 deletions(-) diff --git a/sample/SampleServer/Program.cs b/sample/SampleServer/Program.cs index b872475aa..4ed1e6479 100644 --- a/sample/SampleServer/Program.cs +++ b/sample/SampleServer/Program.cs @@ -53,9 +53,6 @@ static async Task MainAsync(string[] args) .WithHandler() .WithHandler() .WithHandler() - // Linking here because the spec changed but vscode is behind - .WithLink(TextDocumentNames.SemanticTokensFull, "textDocument/semanticTokens") - .WithLink(TextDocumentNames.SemanticTokensFullDelta, "textDocument/semanticTokens/edits") .WithServices(x => x.AddLogging(b => b.SetMinimumLevel(LogLevel.Trace))) .WithServices(services => { services.AddSingleton(provider => { diff --git a/src/Protocol/Document/Proposals/ISemanticTokensDeltaHandler.cs b/src/Protocol/Document/Proposals/ISemanticTokensDeltaHandler.cs index 18f8be8ad..431e46e32 100644 --- a/src/Protocol/Document/Proposals/ISemanticTokensDeltaHandler.cs +++ b/src/Protocol/Document/Proposals/ISemanticTokensDeltaHandler.cs @@ -22,14 +22,14 @@ public interface ISemanticTokensHandler : IJsonRpcRequestHandler, - IRegistration, ICapability + IRegistration, ICapability, IDoesNotParticipateInRegistration { } [Obsolete(Constants.Proposal)] [Parallel, Method(TextDocumentNames.SemanticTokensRange, Direction.ClientToServer)] public interface ISemanticTokensRangeHandler : IJsonRpcRequestHandler, - IRegistration, ICapability + IRegistration, ICapability, IDoesNotParticipateInRegistration { } diff --git a/src/Protocol/IRegistration.cs b/src/Protocol/IRegistration.cs index 2ffe097a8..3d67a6a1a 100644 --- a/src/Protocol/IRegistration.cs +++ b/src/Protocol/IRegistration.cs @@ -5,4 +5,12 @@ public interface IRegistration { TOptions GetRegistrationOptions(); } + + /// + /// Identifies a handler that does not participate in dynamic registration. + /// + public interface IDoesNotParticipateInRegistration + { + + } } diff --git a/src/Protocol/Shared/LspHandlerDescriptor.cs b/src/Protocol/Shared/LspHandlerDescriptor.cs index ef6f6a0f4..2af770606 100644 --- a/src/Protocol/Shared/LspHandlerDescriptor.cs +++ b/src/Protocol/Shared/LspHandlerDescriptor.cs @@ -27,7 +27,8 @@ public LspHandlerDescriptor( Func allowsDynamicRegistration, Type capabilityType, RequestProcessType? requestProcessType, - Action disposeAction) + Action disposeAction, + ILspHandlerTypeDescriptor typeDescriptor) { _disposeAction = disposeAction; Id = Guid.NewGuid(); @@ -76,6 +77,7 @@ public LspHandlerDescriptor( z.IsGenericType && typeof(IJsonRpcNotificationHandler<>).IsAssignableFrom(z.GetGenericTypeDefinition())); IsRequest = !IsNotification; RequestProcessType = requestProcessType; + TypeDescriptor = typeDescriptor; } public Type ImplementationType { get; } @@ -106,6 +108,7 @@ public LspHandlerDescriptor( public bool IsNotification { get; } public bool IsRequest { get; } public RequestProcessType? RequestProcessType { get; } + public ILspHandlerTypeDescriptor TypeDescriptor { get; } public void Dispose() { diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index b16df060b..701540cb1 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -523,6 +523,11 @@ private IDisposable RegisterHandlers(IEnumerable collecti var registrations = new List(); foreach (var descriptor in collection) { + if (descriptor is LspHandlerDescriptor lspHandlerDescriptor && + typeof(IDoesNotParticipateInRegistration).IsAssignableFrom(lspHandlerDescriptor.TypeDescriptor.HandlerType)) + { + continue; + } if (descriptor.HasCapability && _supportedCapabilities.AllowsDynamicRegistration(descriptor.CapabilityType)) { if (descriptor.RegistrationOptions is IWorkDoneProgressOptions wdpo) diff --git a/src/Shared/SharedHandlerCollection.cs b/src/Shared/SharedHandlerCollection.cs index 12c5c5e88..0ae541444 100644 --- a/src/Shared/SharedHandlerCollection.cs +++ b/src/Shared/SharedHandlerCollection.cs @@ -54,8 +54,15 @@ IDisposable IHandlersManager.AddLink(string sourceMethod, string destinationMeth { var source = _handlers.First(z => z.Method == sourceMethod); LspHandlerDescriptor descriptor = null; - descriptor = GetDescriptor(destinationMethod, source.HandlerType, source.Handler, - source.RequestProcessType.HasValue ? new JsonRpcHandlerOptions() {RequestProcessType = source.RequestProcessType.Value} : null); + descriptor = GetDescriptor( + destinationMethod, + source.HandlerType, + source.Handler, + source.RequestProcessType.HasValue ? new JsonRpcHandlerOptions() {RequestProcessType = source.RequestProcessType.Value} : null, + source.TypeDescriptor, + source.HandlerType, + source.RegistrationType, + source.CapabilityType); _handlers.Add(descriptor); var cd = new CompositeDisposable(); if (descriptor.Handler is ITextDocumentIdentifier textDocumentIdentifier) @@ -141,7 +148,9 @@ public LspHandlerDescriptorDisposable Add(params IJsonRpcHandler[] handlers) foreach (var (method, implementedInterface) in handler.GetType().GetTypeInfo() .ImplementedInterfaces .Select(x => (method: HandlerTypeDescriptorHelper.GetMethodName(x), implementedInterface: x)) - .Where(x => !string.IsNullOrWhiteSpace(x.method))) + .Distinct(new EqualityComparer()) + .Where(x => !string.IsNullOrWhiteSpace(x.method)) + ) { var descriptor = GetDescriptor(method, implementedInterface, handler, null); descriptors.Add(descriptor); @@ -156,6 +165,20 @@ public LspHandlerDescriptorDisposable Add(params IJsonRpcHandler[] handlers) return new LspHandlerDescriptorDisposable(descriptors, cd); } + class EqualityComparer : IEqualityComparer<(string method, Type implementedInterface)> + { + + public bool Equals((string method, Type implementedInterface) x, (string method, Type implementedInterface) y) + { + return x.method?.Equals(y.method) == true; + } + + public int GetHashCode((string method, Type implementedInterface) obj) + { + return obj.method?.GetHashCode() ?? 0; + } + } + private LspHandlerDescriptorDisposable Add(IJsonRpcHandler[] handlers, JsonRpcHandlerOptions options) { var descriptors = new HashSet(); @@ -196,12 +219,17 @@ private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJso var typeDescriptor = LspHandlerTypeDescriptorHelper.GetHandlerTypeDescriptor(method); var @interface = HandlerTypeDescriptorHelper.GetHandlerInterface(handlerType); var registrationType = typeDescriptor?.RegistrationType ?? - HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handlerType) ?? - HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handler.GetType()); + HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handlerType); var capabilityType = typeDescriptor?.CapabilityType ?? - HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handlerType) ?? - HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handler.GetType()); + HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handlerType); + return GetDescriptor(method, handlerType, handler, options, typeDescriptor, @interface, registrationType, capabilityType); + } + + private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJsonRpcHandler handler, JsonRpcHandlerOptions options, + ILspHandlerTypeDescriptor typeDescriptor, + Type @interface, Type registrationType, Type capabilityType) + { Type @params = null; object registrationOptions = null; if (@interface.GetTypeInfo().IsGenericType) @@ -256,7 +284,8 @@ private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJso (registrationType == null ? (Func) (() => false) : (() => _supportedCapabilities.AllowsDynamicRegistration(capabilityType))), capabilityType, requestProcessType, - () => { _handlers.RemoveWhere(d => d.Handler == handler); }); + () => { _handlers.RemoveWhere(d => d.Handler == handler); }, + typeDescriptor); return descriptor; } diff --git a/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs b/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs index bc5eae7b1..9c8c52521 100644 --- a/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs +++ b/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs @@ -102,6 +102,8 @@ public async Task Should_Gather_Linked_Registrations() await Events.Settle().Take(2); client.RegistrationManager.CurrentRegistrations.Should().Contain(x => x.Method == TextDocumentNames.SemanticTokensFull); + client.RegistrationManager.CurrentRegistrations.Should().NotContain(x => x.Method == TextDocumentNames.SemanticTokensFullDelta); + client.RegistrationManager.CurrentRegistrations.Should().NotContain(x => x.Method == TextDocumentNames.SemanticTokensRange); client.RegistrationManager.CurrentRegistrations.Should().Contain(x => x.Method == "@/" + TextDocumentNames.SemanticTokensFull); } diff --git a/test/Lsp.Tests/Matchers/ExecuteCommandHandlerMatcherTests.cs b/test/Lsp.Tests/Matchers/ExecuteCommandHandlerMatcherTests.cs index ce938302b..13ded6b42 100644 --- a/test/Lsp.Tests/Matchers/ExecuteCommandHandlerMatcherTests.cs +++ b/test/Lsp.Tests/Matchers/ExecuteCommandHandlerMatcherTests.cs @@ -70,7 +70,8 @@ public void Should_Return_Handler_Descriptor() () => true, typeof(ExecuteCommandCapability), null, - () => { }) + () => { }, + Substitute.For()) }); // Then diff --git a/test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs b/test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs index 86abc8b4e..811018cc9 100644 --- a/test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs +++ b/test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs @@ -69,7 +69,8 @@ public void Should_Not_Throw_Given_Another_Descriptor() () => false, null, null, - () => { }); + () => { }, + Substitute.For()); var handlerMatcher = new ResolveCommandPipeline( new RequestContext() {Descriptor = handlerDescriptor}, LoggerFactory.CreateLogger>()); @@ -104,7 +105,8 @@ public void Should_Return_CodeLensResolve_Descriptor() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), new LspHandlerDescriptor(TextDocumentNames.CodeLensResolve, "Key2", resolveHandler2, @@ -115,7 +117,8 @@ public void Should_Return_CodeLensResolve_Descriptor() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), }) .ToArray(); @@ -145,7 +148,8 @@ public void Should_Handle_Null_Data() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), }) .ToArray(); @@ -177,7 +181,8 @@ public void Should_Handle_Simple_Json_Data() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), }) .ToArray(); @@ -211,7 +216,8 @@ public void Should_Return_CompletionResolve_Descriptor() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), new LspHandlerDescriptor(TextDocumentNames.CompletionResolve, "Key2", resolveHandler2, @@ -222,7 +228,8 @@ public void Should_Return_CompletionResolve_Descriptor() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), }) .ToArray(); @@ -263,7 +270,8 @@ public void Should_Deal_WithHandlers_That_Not_Also_Resolvers() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), new LspHandlerDescriptor(TextDocumentNames.CompletionResolve, "Key2", resolveHandler2 as IJsonRpcHandler, @@ -274,7 +282,8 @@ public void Should_Deal_WithHandlers_That_Not_Also_Resolvers() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), }) .ToArray(); @@ -311,7 +320,8 @@ public void Should_Deal_WithHandlers_That_Not_Also_Resolvers2() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), new LspHandlerDescriptor(TextDocumentNames.CompletionResolve, "Key2", resolveHandler2 as IJsonRpcHandler, @@ -322,7 +332,8 @@ public void Should_Deal_WithHandlers_That_Not_Also_Resolvers2() () => false, null, null, - () => { }), + () => { }, + Substitute.For()), }) .ToArray(); @@ -351,7 +362,8 @@ public async Task Should_Update_CompletionItems_With_HandlerType() () => false, null, null, - () => { }); + () => { }, + Substitute.For()); var handlerMatcher = new ResolveCommandPipeline( new RequestContext() {Descriptor = descriptor}, Substitute.For>>()); @@ -395,7 +407,8 @@ public async Task Should_Update_CodeLensContainer_With_HandlerType() () => false, null, null, - () => { }); + () => { }, + Substitute.For()); var handlerMatcher = new ResolveCommandPipeline( new RequestContext() {Descriptor = descriptor}, Substitute.For>>()); @@ -439,7 +452,8 @@ public async Task Should_Update_CodeLens_Removing_HandlerType() () => false, null, null, - () => { }); + () => { }, + Substitute.For()); var handlerMatcher = new ResolveCommandPipeline( new RequestContext() {Descriptor = descriptor}, Substitute.For>>()); diff --git a/vscode-testextension/package-lock.json b/vscode-testextension/package-lock.json index 19e56b8b7..deefca770 100644 --- a/vscode-testextension/package-lock.json +++ b/vscode-testextension/package-lock.json @@ -1,430 +1,430 @@ { - "name": "language-client-example", - "version": "0.0.1", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/mocha": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.0.0.tgz", - "integrity": "sha512-jWeYcTo3sCH/rMgsdYXDTO85GNRyTCII5dayMIu/ZO4zbEot1E3iNGaOwpLReLUHjeNQFkgeNNVYlY4dX6azQQ==", - "dev": true - }, - "@types/node": { - "version": "14.0.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.24.tgz", - "integrity": "sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA==", - "dev": true - }, - "agent-base": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", - "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "name": "language-client-example", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "@types/mocha": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.0.0.tgz", + "integrity": "sha512-jWeYcTo3sCH/rMgsdYXDTO85GNRyTCII5dayMIu/ZO4zbEot1E3iNGaOwpLReLUHjeNQFkgeNNVYlY4dX6azQQ==", + "dev": true + }, + "@types/node": { + "version": "14.0.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.25.tgz", + "integrity": "sha512-okMqUHqrMlGOxfDZliX1yFX5MV6qcd5PpRz96XYtjkM0Ws/hwg23FMUqt6pETrVRZS+EKUB5HY19mmo54EuQbA==", + "dev": true }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "typescript": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", - "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", - "dev": true - }, - "vscode": { - "version": "1.1.37", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.37.tgz", - "integrity": "sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg==", - "dev": true, - "requires": { - "glob": "^7.1.2", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "mocha": "^5.2.0", - "semver": "^5.4.1", - "source-map-support": "^0.5.0", - "vscode-test": "^0.4.1" - } - }, - "vscode-jsonrpc": { - "version": "6.0.0-next.3", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.3.tgz", - "integrity": "sha512-bkAtRMXbTwU1pAXnlbkAMnrqXZX3q2/zttkcnPZOsDqgoycO2L7GK2aN3K5qCMZmhItwBU185T78Q9YH0v5jEA==" - }, - "vscode-languageclient": { - "version": "7.0.0-next.7", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0-next.7.tgz", - "integrity": "sha512-D6CuCDDiwcTyg6EI5E7k7FQZHjfkXpjsI67Am+o89sxPr/1Owrp3246crnD4EHGgp+xx+9u/fuibwRtw9PWJVw==", - "requires": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "3.16.0-next.5" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "vscode-languageserver-protocol": { - "version": "3.16.0-next.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.5.tgz", - "integrity": "sha512-MVuLT4d5tdDo/14laViyZY+p1HT7wYDwJdvGmo8mCfkgON5c10AABhtqjD+LccidBcwdbKy+4dwwUUxiNg/8PA==", - "requires": { - "vscode-jsonrpc": "6.0.0-next.3", - "vscode-languageserver-types": "3.16.0-next.2" - } - }, - "vscode-languageserver-types": { - "version": "3.16.0-next.2", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz", - "integrity": "sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==" - }, - "vscode-test": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-0.4.3.tgz", - "integrity": "sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==", - "dev": true, - "requires": { - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1" - }, - "dependencies": { "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", + "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true }, "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } }, "https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "typescript": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "dev": true + }, + "vscode": { + "version": "1.1.37", + "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.37.tgz", + "integrity": "sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg==", + "dev": true, + "requires": { + "glob": "^7.1.2", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "mocha": "^5.2.0", + "semver": "^5.4.1", + "source-map-support": "^0.5.0", + "vscode-test": "^0.4.1" + } + }, + "vscode-jsonrpc": { + "version": "6.0.0-next.4", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.4.tgz", + "integrity": "sha512-nIXUeSMKfqvqSG75s1JuUy0UgjE3d0NERjGz7AUGDFXX0/roVUEbaio5VBdus30nty8v0FCf/6MbCSrH5RybcQ==" + }, + "vscode-languageclient": { + "version": "7.0.0-next.8", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0-next.8.tgz", + "integrity": "sha512-qgQBImLm24tjhvc42YbLLRYWibwSgccUruy0GhVOr69BZRfT3CkMeeQfjIdumrfCCYPu/vPdJ6KjtAYamBCESw==", + "requires": { + "semver": "^6.3.0", + "vscode-languageserver-protocol": "3.16.0-next.6" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "vscode-languageserver-protocol": { + "version": "3.16.0-next.6", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.6.tgz", + "integrity": "sha512-tW8LMFBBr6WJ33mzYAjiLTu/4tch9nvJ+rBhUNzJ8X1zNR39vj8CV3FsnrxzAqvOB+qBWEOQa0tjupW1mNo2GQ==", + "requires": { + "vscode-jsonrpc": "6.0.0-next.4", + "vscode-languageserver-types": "3.16.0-next.3" + } + }, + "vscode-languageserver-types": { + "version": "3.16.0-next.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.3.tgz", + "integrity": "sha512-s/z5ZqSe7VpoXJ6JQcvwRiPPA3nG0nAcJ/HH03zoU6QaFfnkcgPK+HshC3WKPPnC2G08xA0iRB6h7kmyBB5Adg==" + }, + "vscode-test": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-0.4.3.tgz", + "integrity": "sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==", + "dev": true, + "requires": { + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true } - } } diff --git a/vscode-testextension/package.json b/vscode-testextension/package.json index 0eea6966c..7b4f7f137 100644 --- a/vscode-testextension/package.json +++ b/vscode-testextension/package.json @@ -47,11 +47,12 @@ }, "devDependencies": { "@types/mocha": "^8.0.0", - "@types/node": "^14.0.24", + "@types/node": "^14.0.25", "typescript": "^3.9.7", "vscode": "^1.1.37" }, "dependencies": { - "vscode-languageclient": "^7.0.0-next.7" + "vscode-languageclient": "^7.0.0-next.8", + "vscode-languageserver-protocol": "^3.16.0-next.6" } } From 3028bba50c5b18a04ba4b4cd5652606ae5b590ff Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Thu, 23 Jul 2020 21:30:13 -0400 Subject: [PATCH 08/10] fixed issue with dynamic registration and the sub handlers for semantic tokens --- src/Server/LanguageServer.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index 701540cb1..a146956f5 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -478,21 +478,11 @@ private async Task DynamicallyRegisterHandlers(Registration[] registrations) if (registrations.Length == 0) return; // No dynamic registrations supported by client. + var @params = new RegistrationParams() {Registrations = registrations}; + await _initializeComplete; - // Some clients (read: vscode) will throw errors on the first unhandled registration it encounters (and never registers the rest) - // This is not really desirable as if we send a registration they don't support... that shouldn't break any unprocessed registrations - // So in order to fix this we just send each registration along as separate requests all at once. - await registrations - .ToObservable() - .Select(z => Observable.FromAsync(ct => Client.RegisterCapability(new RegistrationParams() {Registrations = new RegistrationContainer(z)}, ct)) - .Catch(_ => { - this.LogWarning($"Unable to dynamically register capability '{z.Method}' perhaps it is not supported?"); - return Observable.Empty(); - }) - ) - .Merge() - .ToTask(); + await Client.RegisterCapability(@params); } public IObservable Start => _initializeComplete.AsObservable(); @@ -528,6 +518,7 @@ private IDisposable RegisterHandlers(IEnumerable collecti { continue; } + if (descriptor.HasCapability && _supportedCapabilities.AllowsDynamicRegistration(descriptor.CapabilityType)) { if (descriptor.RegistrationOptions is IWorkDoneProgressOptions wdpo) From 3e5d65af2876ee25075bfa11ccf2ecd9dbcd547c Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Thu, 23 Jul 2020 23:10:55 -0400 Subject: [PATCH 09/10] fixed failed tests --- src/Server/LanguageServer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index a146956f5..758c22c5a 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -514,6 +514,7 @@ private IDisposable RegisterHandlers(IEnumerable collecti foreach (var descriptor in collection) { if (descriptor is LspHandlerDescriptor lspHandlerDescriptor && + lspHandlerDescriptor.TypeDescriptor?.HandlerType != null && typeof(IDoesNotParticipateInRegistration).IsAssignableFrom(lspHandlerDescriptor.TypeDescriptor.HandlerType)) { continue; From 01341907536db3d3b1ed93ba2e1a6b52b95d94cb Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Thu, 23 Jul 2020 23:25:45 -0400 Subject: [PATCH 10/10] Added back missing comments --- .../Models/Proposals/SemanticTokensPartialResult.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs b/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs index 7e27b5a53..1f47e2b0b 100644 --- a/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs +++ b/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs @@ -3,9 +3,17 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals { + /// + /// @since 3.16.0 + /// [Obsolete(Constants.Proposal)] public class SemanticTokensPartialResult { + /// + /// The actual tokens. For a detailed description about how the data is + /// structured pls see + /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 + /// public ImmutableArray Data { get; set; } } }