From dadf6bc29d06f1a00c9d509f8bc75f7f4b97a622 Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Tue, 10 Oct 2017 16:52:02 -0400 Subject: [PATCH 1/2] Try to fix issue with handlers getting registered twice --- src/Lsp/LanguageServer.cs | 56 ++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/Lsp/LanguageServer.cs b/src/Lsp/LanguageServer.cs index 3d5f99831..ded62daa4 100644 --- a/src/Lsp/LanguageServer.cs +++ b/src/Lsp/LanguageServer.cs @@ -122,24 +122,27 @@ async Task IRequestHandler } } + var textDocumentCapabilities = Client.Capabilities.TextDocument; + var workspaceCapabilities = Client.Capabilities.Workspace; + var serverCapabilities = new ServerCapabilities() { - CodeActionProvider = HasHandler(), - CodeLensProvider = GetOptions(CodeLensOptions.Of), - CompletionProvider = GetOptions(CompletionOptions.Of), - DefinitionProvider = HasHandler(), - DocumentFormattingProvider = HasHandler(), - DocumentHighlightProvider = HasHandler(), - DocumentLinkProvider = GetOptions(DocumentLinkOptions.Of), - DocumentOnTypeFormattingProvider = GetOptions(DocumentOnTypeFormattingOptions.Of), - DocumentRangeFormattingProvider = HasHandler(), - DocumentSymbolProvider = HasHandler(), - ExecuteCommandProvider = GetOptions(ExecuteCommandOptions.Of), - HoverProvider = HasHandler(), - ReferencesProvider = HasHandler(), - RenameProvider = HasHandler(), - SignatureHelpProvider = GetOptions(SignatureHelpOptions.Of), - WorkspaceSymbolProvider = HasHandler() + CodeActionProvider = HasHandler(textDocumentCapabilities.CodeAction), + CodeLensProvider = GetOptions(textDocumentCapabilities.CodeLens, CodeLensOptions.Of), + CompletionProvider = GetOptions(textDocumentCapabilities.Completion, CompletionOptions.Of), + DefinitionProvider = HasHandler(textDocumentCapabilities.Definition), + DocumentFormattingProvider = HasHandler(textDocumentCapabilities.Formatting), + DocumentHighlightProvider = HasHandler(textDocumentCapabilities.DocumentHighlight), + DocumentLinkProvider = GetOptions(textDocumentCapabilities.DocumentLink, DocumentLinkOptions.Of), + DocumentOnTypeFormattingProvider = GetOptions(textDocumentCapabilities.OnTypeFormatting, DocumentOnTypeFormattingOptions.Of), + DocumentRangeFormattingProvider = HasHandler(textDocumentCapabilities.RangeFormatting), + DocumentSymbolProvider = HasHandler(textDocumentCapabilities.DocumentSymbol), + ExecuteCommandProvider = GetOptions(workspaceCapabilities.ExecuteCommand, ExecuteCommandOptions.Of), + HoverProvider = HasHandler(textDocumentCapabilities.Hover), + ReferencesProvider = HasHandler(textDocumentCapabilities.References), + RenameProvider = HasHandler(textDocumentCapabilities.Rename), + SignatureHelpProvider = GetOptions(textDocumentCapabilities.SignatureHelp, SignatureHelpOptions.Of), + WorkspaceSymbolProvider = HasHandler(workspaceCapabilities.Symbol) }; var textSyncHandler = _collection @@ -194,19 +197,34 @@ public Task Handle() return Task.CompletedTask; } - private bool HasHandler() + private bool HasHandler(DynamicCapability capability) { - return _collection.Any(z => z.Handler is T); + return capability.DynamicRegistration ? false : _collection.Any(z => z.Handler is T); } - private T GetOptions(Func action) + private bool HasHandler(Supports capability) + { + if (!capability.IsSupported) return false; + return HasHandler(capability.Value); + } + + private T GetOptions(DynamicCapability capability, Func action) where T : class { + if (capability.DynamicRegistration) return null; + return _collection .Select(x => x.Registration?.RegisterOptions is O cl ? action(cl) : null) .FirstOrDefault(x => x != null); } + private T GetOptions(Supports capability, Func action) + where T : class + { + if (!capability.IsSupported) return null; + return GetOptions(capability.Value, action); + } + private void ProcessCapabilties(object instance) { var values = instance From 47f81b9cf31556abcdce40c1cad35768a65d4ddf Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Tue, 10 Oct 2017 21:46:22 -0400 Subject: [PATCH 2/2] Changed around how handlers are created --- src/Lsp/HandlerCollection.cs | 16 ++++++++++------ ...tableDisposable.cs => ImmutableDisposable.cs} | 8 ++++---- src/Lsp/LanguageServer.cs | 8 ++++---- 3 files changed, 18 insertions(+), 14 deletions(-) rename src/Lsp/{ImutableDisposable.cs => ImmutableDisposable.cs} (70%) diff --git a/src/Lsp/HandlerCollection.cs b/src/Lsp/HandlerCollection.cs index f3d6b89a4..386933e08 100644 --- a/src/Lsp/HandlerCollection.cs +++ b/src/Lsp/HandlerCollection.cs @@ -23,14 +23,14 @@ IEnumerator IEnumerable.GetEnumerator() return GetEnumerator(); } - public IDisposable Add(params IJsonRpcHandler[] handlers) + public IDisposable Add(IEnumerable handlers) { - return Add(handlers.AsEnumerable()); + return Add(handlers.ToArray()); } - public IDisposable Add(IEnumerable handlers) + public IDisposable Add(params IJsonRpcHandler[] handlers) { - var descriptors = new List(); + var descriptors = new HashSet(); foreach (var handler in handlers) { foreach (var implementedInterface in handler.GetType().GetTypeInfo() @@ -65,11 +65,15 @@ public IDisposable Add(IEnumerable handlers) () => _handlers.RemoveWhere(instance => instance.Handler == handler)); descriptors.Add(h); - _handlers.Add(h); } } - return new ImutableDisposable(descriptors); + foreach (var handler in descriptors) + { + _handlers.Add(handler); + } + + return new ImmutableDisposable(descriptors); } private Type UnwrapGenericType(Type genericType, Type type) diff --git a/src/Lsp/ImutableDisposable.cs b/src/Lsp/ImmutableDisposable.cs similarity index 70% rename from src/Lsp/ImutableDisposable.cs rename to src/Lsp/ImmutableDisposable.cs index 8189d3e10..781410f8f 100644 --- a/src/Lsp/ImutableDisposable.cs +++ b/src/Lsp/ImmutableDisposable.cs @@ -3,16 +3,16 @@ namespace OmniSharp.Extensions.LanguageServer { - class ImutableDisposable : IDisposable + class ImmutableDisposable : IDisposable { private readonly IEnumerable _instances; - public ImutableDisposable(IEnumerable instances) + public ImmutableDisposable(IEnumerable instances) { _instances = instances; } - public ImutableDisposable(params IDisposable[] instances) + public ImmutableDisposable(params IDisposable[] instances) { _instances = instances; } @@ -25,4 +25,4 @@ public void Dispose() } } } -} \ No newline at end of file +} diff --git a/src/Lsp/LanguageServer.cs b/src/Lsp/LanguageServer.cs index ded62daa4..ba932c795 100644 --- a/src/Lsp/LanguageServer.cs +++ b/src/Lsp/LanguageServer.cs @@ -60,16 +60,16 @@ public IDisposable AddHandler(IJsonRpcHandler handler) return AddHandler(handler); } - public IDisposable AddHandlers(params IJsonRpcHandler[] handlers) + public IDisposable AddHandlers(IEnumerable handlers) { - return AddHandlers(handlers.AsEnumerable()); + return AddHandlers(handlers.ToArray()); } - public IDisposable AddHandlers(IEnumerable handlers) + public IDisposable AddHandlers(params IJsonRpcHandler[] handlers) { var handlerDisposable = _collection.Add(handlers); - return new ImutableDisposable( + return new ImmutableDisposable( handlerDisposable, new Disposable(() => {