From 8411ac4d9dc5e8e77b8354efc9bcc8e3a6162ce0 Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Sat, 15 Aug 2020 18:50:32 -0400 Subject: [PATCH] Refactored static HandlerTypeDescriptorHelper to injected as HandlerTypeDescriptorProvider (#319) --- src/Client/LanguageClientOptions.cs | 7 +- src/Client/LanguageClientOptionsExtensions.cs | 2 +- .../LanguageClientRegistrationManager.cs | 13 +- ...nguageClientServiceCollectionExtensions.cs | 11 +- src/Client/LspClientReceiver.cs | 11 +- src/Dap.Client/DebugAdapterClientOptions.cs | 5 + .../DebugAdapterRpcOptionsBase.cs | 7 +- src/Dap.Server/DebugAdapterServerOptions.cs | 5 + .../DebugAdapterHandlerCollection.cs | 11 +- ...pterProtocolServiceCollectionExtensions.cs | 3 + src/JsonRpc.Testing/JsonRpcTestOptions.cs | 4 + .../JsonRpcTestOptionsExtensions.cs | 15 ++ src/JsonRpc/HandlerCollection.cs | 12 +- ...er.cs => HandlerTypeDescriptorProvider.cs} | 177 ++++++++++-------- src/JsonRpc/JsonRpcServerOptionsBase.cs | 8 +- ...sonRpcServerServiceCollectionExtensions.cs | 3 + src/JsonRpc/ResponseRouter.cs | 6 +- .../LanguageProtocolRpcOptionsBase.cs | 6 +- .../Shared/LspHandlerTypeDescriptorHelper.cs | 70 ------- .../LspHandlerTypeDescriptorProvider.cs | 102 ++++++++++ src/Server/LanguageServerOptions.cs | 10 +- src/Server/LanguageServerOptionsExtensions.cs | 9 + ...nguageServerServiceCollectionExtensions.cs | 11 +- src/Server/LspServerReceiver.cs | 9 +- src/Server/Server.csproj | 4 - ...uageProtocolServiceCollectionExtensions.cs | 4 + src/Shared/RequestProcessIdentifier.cs | 23 +-- src/Shared/SharedHandlerCollection.cs | 12 +- src/Testing/LanguageProtocolTestBase.cs | 4 + src/Testing/LanguageServerTestBase.cs | 2 + test/Dap.Tests/FoundationTests.cs | 23 ++- test/JsonRpc.Tests/HandlerResolverTests.cs | 4 +- .../MediatorTestsNotificationHandler.cs | 2 +- .../MediatorTestsNotificationHandlerOfT.cs | 2 +- .../MediatorTestsRequestHandlerOfTRequest.cs | 2 +- ...rTestsRequestHandlerOfTRequestTResponse.cs | 2 +- test/JsonRpc.Tests/RequestRouterTests.cs | 8 +- test/JsonRpc.Tests/ResponseRouterTests.cs | 6 +- .../ClientCapabilityProviderFixture.cs | 7 +- .../ClientCapabilityProviderTests.cs | 23 ++- test/Lsp.Tests/FoundationTests.cs | 23 ++- test/Lsp.Tests/HandlerResolverTests.cs | 35 ++-- test/Lsp.Tests/LspRequestRouterTests.cs | 62 +++++- .../Matchers/TextDocumentMatcherTests.cs | 23 ++- ...rTestsRequestHandlerOfTRequestTResponse.cs | 6 +- 45 files changed, 530 insertions(+), 264 deletions(-) rename src/JsonRpc/{HandlerTypeDescriptorHelper.cs => HandlerTypeDescriptorProvider.cs} (59%) delete mode 100644 src/Protocol/Shared/LspHandlerTypeDescriptorHelper.cs create mode 100644 src/Protocol/Shared/LspHandlerTypeDescriptorProvider.cs diff --git a/src/Client/LanguageClientOptions.cs b/src/Client/LanguageClientOptions.cs index d9e00c736..1ab0e10d8 100644 --- a/src/Client/LanguageClientOptions.cs +++ b/src/Client/LanguageClientOptions.cs @@ -8,11 +8,16 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Client; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Shared; namespace OmniSharp.Extensions.LanguageServer.Client { public class LanguageClientOptions : LanguageProtocolRpcOptionsBase, ILanguageClientRegistry { + public LanguageClientOptions() + { + WithAssemblies(typeof(LanguageClientOptions).Assembly, typeof(LspRequestRouter).Assembly); + } public ClientCapabilities ClientCapabilities { get; set; } = new ClientCapabilities { Experimental = new Dictionary(), Window = new WindowClientCapabilities(), @@ -36,8 +41,6 @@ public string RootPath public object InitializationOptions { get; set; } - public ILspClientReceiver Receiver { get; set; } = new LspClientReceiver(); - ILanguageClientRegistry IJsonRpcHandlerRegistry.AddHandler(string method, IJsonRpcHandler handler, JsonRpcHandlerOptions options) => AddHandler(method, handler, options); diff --git a/src/Client/LanguageClientOptionsExtensions.cs b/src/Client/LanguageClientOptionsExtensions.cs index 4d50017f4..80d7e53bf 100644 --- a/src/Client/LanguageClientOptionsExtensions.cs +++ b/src/Client/LanguageClientOptionsExtensions.cs @@ -23,7 +23,7 @@ public static LanguageClientOptions WithReceiver( ILspClientReceiver serverReceiver ) { - options.Receiver = serverReceiver; + options.Services.AddSingleton(serverReceiver); return options; } diff --git a/src/Client/LanguageClientRegistrationManager.cs b/src/Client/LanguageClientRegistrationManager.cs index c798044d7..8bed4f93c 100644 --- a/src/Client/LanguageClientRegistrationManager.cs +++ b/src/Client/LanguageClientRegistrationManager.cs @@ -22,13 +22,18 @@ namespace OmniSharp.Extensions.LanguageServer.Client internal class LanguageClientRegistrationManager : IRegisterCapabilityHandler, IUnregisterCapabilityHandler, IRegistrationManager, IDisposable { private readonly ISerializer _serializer; + private readonly ILspHandlerTypeDescriptorProvider _handlerTypeDescriptorProvider; private readonly ILogger _logger; private readonly ConcurrentDictionary _registrations; private readonly ReplaySubject> _registrationSubject; - public LanguageClientRegistrationManager(ISerializer serializer, ILogger logger) + public LanguageClientRegistrationManager( + ISerializer serializer, + ILspHandlerTypeDescriptorProvider handlerTypeDescriptorProvider, + ILogger logger) { _serializer = serializer; + _handlerTypeDescriptorProvider = handlerTypeDescriptorProvider; _logger = logger; _registrations = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); _registrationSubject = new ReplaySubject>(1); @@ -65,7 +70,7 @@ public void RegisterCapabilities(ServerCapabilities serverCapabilities) serverCapabilities )) { - var method = LspHandlerTypeDescriptorHelper.GetMethodForRegistrationOptions(registrationOptions); + var method = _handlerTypeDescriptorProvider.GetMethodForRegistrationOptions(registrationOptions); if (method == null) { _logger.LogWarning("Unable to find method for given {@RegistrationOptions}", registrationOptions); @@ -91,7 +96,7 @@ public void RegisterCapabilities(ServerCapabilities serverCapabilities) .Workspace )) { - var method = LspHandlerTypeDescriptorHelper.GetMethodForRegistrationOptions(registrationOptions); + var method = _handlerTypeDescriptorProvider.GetMethodForRegistrationOptions(registrationOptions); if (method == null) { // TODO: Log this @@ -117,7 +122,7 @@ private void Register(params Registration[] registrations) private void Register(Registration registration) { - var registrationType = LspHandlerTypeDescriptorHelper.GetRegistrationType(registration.Method); + var registrationType = _handlerTypeDescriptorProvider.GetRegistrationType(registration.Method); if (registrationType == null) { _registrations.AddOrUpdate(registration.Id, x => registration, (a, b) => registration); diff --git a/src/Client/LanguageClientServiceCollectionExtensions.cs b/src/Client/LanguageClientServiceCollectionExtensions.cs index d20569210..48f463fb9 100644 --- a/src/Client/LanguageClientServiceCollectionExtensions.cs +++ b/src/Client/LanguageClientServiceCollectionExtensions.cs @@ -18,15 +18,14 @@ public static class LanguageClientServiceCollectionExtensions { internal static IContainer AddLanguageClientInternals(this IContainer container, LanguageClientOptions options, IServiceProvider outerServiceProvider) { - if (options.Receiver == null) - { - throw new ArgumentException("Receiver is missing!", nameof(options)); - } - container = container.AddLanguageProtocolInternals(options); container.RegisterInstance(options.ClientCapabilities); - container.RegisterInstanceMany(options.Receiver); + container.RegisterMany( + reuse: Reuse.Singleton, + nonPublicServiceTypes: true, + ifAlreadyRegistered: IfAlreadyRegistered.Keep + ); if (options.OnUnhandledException != null) { container.RegisterInstance(options.OnUnhandledException); diff --git a/src/Client/LspClientReceiver.cs b/src/Client/LspClientReceiver.cs index 235b6649b..360af0c1f 100644 --- a/src/Client/LspClientReceiver.cs +++ b/src/Client/LspClientReceiver.cs @@ -4,14 +4,21 @@ using OmniSharp.Extensions.JsonRpc.Client; using OmniSharp.Extensions.JsonRpc.Server; using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Shared; using OmniSharp.Extensions.LanguageServer.Protocol.Window; namespace OmniSharp.Extensions.LanguageServer.Client { public class LspClientReceiver : Receiver, ILspClientReceiver { + private readonly ILspHandlerTypeDescriptorProvider _handlerTypeDescriptorProvider; private bool _initialized; + public LspClientReceiver(ILspHandlerTypeDescriptorProvider handlerTypeDescriptorProvider) + { + _handlerTypeDescriptorProvider = handlerTypeDescriptorProvider; + } + public override (IEnumerable results, bool hasResponse) GetRequests(JToken container) { if (_initialized) return base.GetRequests(container); @@ -23,7 +30,7 @@ public override (IEnumerable results, bool hasResponse) GetRequests(JToke foreach (var item in results) { if (item.IsRequest && - HandlerTypeDescriptorHelper.IsMethodName(item.Request.Method, typeof(IShowMessageRequestHandler))) + _handlerTypeDescriptorProvider.IsMethodName(item.Request.Method, typeof(IShowMessageRequestHandler))) { newResults.Add(item); } @@ -32,7 +39,7 @@ public override (IEnumerable results, bool hasResponse) GetRequests(JToke newResults.Add(item); } else if (item.IsNotification && - HandlerTypeDescriptorHelper.IsMethodName( + _handlerTypeDescriptorProvider.IsMethodName( item.Notification.Method, typeof(IShowMessageHandler), typeof(ILogMessageHandler), diff --git a/src/Dap.Client/DebugAdapterClientOptions.cs b/src/Dap.Client/DebugAdapterClientOptions.cs index a30eec58e..d6c5a70da 100644 --- a/src/Dap.Client/DebugAdapterClientOptions.cs +++ b/src/Dap.Client/DebugAdapterClientOptions.cs @@ -5,12 +5,17 @@ using OmniSharp.Extensions.DebugAdapter.Protocol; using OmniSharp.Extensions.DebugAdapter.Protocol.Client; using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +using OmniSharp.Extensions.DebugAdapter.Shared; using OmniSharp.Extensions.JsonRpc; namespace OmniSharp.Extensions.DebugAdapter.Client { public class DebugAdapterClientOptions : DebugAdapterRpcOptionsBase, IDebugAdapterClientRegistry, IInitializeRequestArguments { + public DebugAdapterClientOptions() + { + WithAssemblies(typeof(DebugAdapterClientOptions).Assembly, typeof(DebugAdapterRequestRouter).Assembly); + } public override IRequestProcessIdentifier RequestProcessIdentifier { get; set; } = new ParallelRequestProcessIdentifier(); public string ClientId { get; set; } public string ClientName { get; set; } diff --git a/src/Dap.Protocol/DebugAdapterRpcOptionsBase.cs b/src/Dap.Protocol/DebugAdapterRpcOptionsBase.cs index 20d1acd43..f1d936fb7 100644 --- a/src/Dap.Protocol/DebugAdapterRpcOptionsBase.cs +++ b/src/Dap.Protocol/DebugAdapterRpcOptionsBase.cs @@ -8,7 +8,12 @@ namespace OmniSharp.Extensions.DebugAdapter.Protocol { public abstract class DebugAdapterRpcOptionsBase : JsonRpcServerOptionsBase where T : IJsonRpcHandlerRegistry { - public DebugAdapterRpcOptionsBase() => Services.AddLogging(builder => LoggingBuilderAction?.Invoke(builder)); + protected DebugAdapterRpcOptionsBase() + { + Services.AddLogging(builder => LoggingBuilderAction?.Invoke(builder)); + WithAssemblies(typeof(DebugAdapterRpcOptionsBase).Assembly); + } + public ISerializer Serializer { get; set; } = new DapSerializer(); public override IRequestProcessIdentifier RequestProcessIdentifier { get; set; } = new ParallelRequestProcessIdentifier(); internal bool AddDefaultLoggingProvider { get; set; } diff --git a/src/Dap.Server/DebugAdapterServerOptions.cs b/src/Dap.Server/DebugAdapterServerOptions.cs index e8e2509b1..2e8499263 100644 --- a/src/Dap.Server/DebugAdapterServerOptions.cs +++ b/src/Dap.Server/DebugAdapterServerOptions.cs @@ -5,12 +5,17 @@ using OmniSharp.Extensions.DebugAdapter.Protocol; using OmniSharp.Extensions.DebugAdapter.Protocol.Models; using OmniSharp.Extensions.DebugAdapter.Protocol.Server; +using OmniSharp.Extensions.DebugAdapter.Shared; using OmniSharp.Extensions.JsonRpc; namespace OmniSharp.Extensions.DebugAdapter.Server { public class DebugAdapterServerOptions : DebugAdapterRpcOptionsBase, IDebugAdapterServerRegistry { + public DebugAdapterServerOptions() + { + WithAssemblies(typeof(DebugAdapterServerOptions).Assembly, typeof(DebugAdapterRequestRouter).Assembly); + } public Capabilities Capabilities { get; set; } = new Capabilities(); IDebugAdapterServerRegistry IJsonRpcHandlerRegistry.AddHandler(string method, IJsonRpcHandler handler, JsonRpcHandlerOptions options) => diff --git a/src/Dap.Shared/DebugAdapterHandlerCollection.cs b/src/Dap.Shared/DebugAdapterHandlerCollection.cs index 7148360ca..35a917a5e 100644 --- a/src/Dap.Shared/DebugAdapterHandlerCollection.cs +++ b/src/Dap.Shared/DebugAdapterHandlerCollection.cs @@ -16,10 +16,15 @@ internal class DebugAdapterHandlerCollection : IEnumerable, { private ImmutableHashSet _descriptors = ImmutableHashSet.Empty; private readonly IServiceProvider _serviceProvider; + private readonly IHandlerTypeDescriptorProvider _handlerTypeDescriptorProvider; public IEnumerable Descriptors => _descriptors; - public DebugAdapterHandlerCollection(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; + public DebugAdapterHandlerCollection(IServiceProvider serviceProvider, IHandlerTypeDescriptorProvider handlerTypeDescriptorProvider) + { + _serviceProvider = serviceProvider; + _handlerTypeDescriptorProvider = handlerTypeDescriptorProvider; + } public IEnumerator GetEnumerator() => _descriptors.GetEnumerator(); @@ -107,7 +112,7 @@ private CompositeDisposable AddHandler(IJsonRpcHandler handler, JsonRpcHandlerOp var cd = new CompositeDisposable(); foreach (var (method, implementedInterface) in handler.GetType().GetTypeInfo() .ImplementedInterfaces - .Select(x => ( method: HandlerTypeDescriptorHelper.GetMethodName(x), implementedInterface: x )) + .Select(x => ( method: _handlerTypeDescriptorProvider.GetMethodName(x), implementedInterface: x )) .Distinct(new EqualityComparer()) .Where(x => !string.IsNullOrWhiteSpace(x.method)) ) @@ -122,7 +127,7 @@ private CompositeDisposable AddHandler(IJsonRpcHandler handler, JsonRpcHandlerOp private HandlerDescriptor GetDescriptor(string method, Type handlerType, IJsonRpcHandler handler, JsonRpcHandlerOptions options) { - var typeDescriptor = HandlerTypeDescriptorHelper.GetHandlerTypeDescriptor(handlerType); + var typeDescriptor = _handlerTypeDescriptorProvider.GetHandlerTypeDescriptor(handlerType); var @interface = HandlerTypeDescriptorHelper.GetHandlerInterface(handlerType); return GetDescriptor(method, handlerType, handler, options, typeDescriptor, @interface); diff --git a/src/Dap.Shared/DebugAdapterProtocolServiceCollectionExtensions.cs b/src/Dap.Shared/DebugAdapterProtocolServiceCollectionExtensions.cs index 47c2557de..956526636 100644 --- a/src/Dap.Shared/DebugAdapterProtocolServiceCollectionExtensions.cs +++ b/src/Dap.Shared/DebugAdapterProtocolServiceCollectionExtensions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Reflection; using DryIoc; using OmniSharp.Extensions.DebugAdapter.Protocol; using OmniSharp.Extensions.JsonRpc; @@ -15,6 +17,7 @@ internal static IContainer AddDebugAdapterProtocolInternals(this IContainer c } container = container.AddJsonRpcServerCore(options); + container.RegisterInstanceMany(new HandlerTypeDescriptorProvider(options.Assemblies), nonPublicServiceTypes: true); container.RegisterInstanceMany(options.Serializer); container.RegisterInstance(options.RequestProcessIdentifier); diff --git a/src/JsonRpc.Testing/JsonRpcTestOptions.cs b/src/JsonRpc.Testing/JsonRpcTestOptions.cs index 9a299277c..16de931e6 100644 --- a/src/JsonRpc.Testing/JsonRpcTestOptions.cs +++ b/src/JsonRpc.Testing/JsonRpcTestOptions.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; using System.IO.Pipelines; +using System.Linq; +using System.Reflection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -25,5 +28,6 @@ public JsonRpcTestOptions(ILoggerFactory clientLoggerFactory, ILoggerFactory ser public TimeSpan Timeout { get; internal set; } = TimeSpan.FromMilliseconds(500); public TimeSpan CancellationTimeout { get; internal set; } = TimeSpan.FromMinutes(5); public PipeOptions DefaultPipeOptions { get; internal set; } = new PipeOptions(); + public IEnumerable Assemblies { get; set; } = Enumerable.Empty(); } } diff --git a/src/JsonRpc.Testing/JsonRpcTestOptionsExtensions.cs b/src/JsonRpc.Testing/JsonRpcTestOptionsExtensions.cs index 43adfcd1f..1fa284b70 100644 --- a/src/JsonRpc.Testing/JsonRpcTestOptionsExtensions.cs +++ b/src/JsonRpc.Testing/JsonRpcTestOptionsExtensions.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; using System.IO.Pipelines; +using System.Linq; +using System.Reflection; using Microsoft.Extensions.Logging; namespace OmniSharp.Extensions.JsonRpc.Testing @@ -41,5 +44,17 @@ public static JsonRpcTestOptions WithDefaultPipeOptions(this JsonRpcTestOptions options.DefaultPipeOptions = pipeOptions; return options; } + + public static JsonRpcTestOptions WithAssemblies(this JsonRpcTestOptions options, IEnumerable assemblies) + { + options.Assemblies = options.Assemblies.Concat(assemblies).ToArray(); + return options; + } + + public static JsonRpcTestOptions WithAssemblies(this JsonRpcTestOptions options, params Assembly[] assemblies) + { + options.Assemblies = options.Assemblies.Concat(assemblies).ToArray(); + return options; + } } } diff --git a/src/JsonRpc/HandlerCollection.cs b/src/JsonRpc/HandlerCollection.cs index 06a868563..1a1104459 100644 --- a/src/JsonRpc/HandlerCollection.cs +++ b/src/JsonRpc/HandlerCollection.cs @@ -13,11 +13,16 @@ namespace OmniSharp.Extensions.JsonRpc internal class HandlerCollection : IHandlersManager, IEnumerable { private readonly IServiceProvider _serviceProvider; + private readonly IHandlerTypeDescriptorProvider _handlerTypeDescriptorProvider; private ImmutableArray _descriptors = ImmutableArray.Empty; public IEnumerable Descriptors => _descriptors; - public HandlerCollection(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; + public HandlerCollection(IServiceProvider serviceProvider, IHandlerTypeDescriptorProvider handlerTypeDescriptorProvider) + { + _serviceProvider = serviceProvider; + _handlerTypeDescriptorProvider = handlerTypeDescriptorProvider; + } private void Remove(IJsonRpcHandler handler) { @@ -36,13 +41,13 @@ public IDisposable Add(params IJsonRpcHandler[] handlers) foreach (var handler in handlers) { if (_descriptors.Any(z => z.Handler == handler)) continue; - cd.Add(Add(HandlerTypeDescriptorHelper.GetMethodName(handler.GetType()), handler, null)); + cd.Add(Add(_handlerTypeDescriptorProvider.GetMethodName(handler.GetType()), handler, null)); } return cd; } - public IDisposable Add(IJsonRpcHandler handler, JsonRpcHandlerOptions options) => Add(HandlerTypeDescriptorHelper.GetMethodName(handler.GetType()), handler, options); + public IDisposable Add(IJsonRpcHandler handler, JsonRpcHandlerOptions options) => Add(_handlerTypeDescriptorProvider.GetMethodName(handler.GetType()), handler, options); public IDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOptions options) { @@ -64,6 +69,7 @@ public IDisposable Add(string method, IJsonRpcHandler handler, JsonRpcHandlerOpt var requestProcessType = options?.RequestProcessType ?? + _handlerTypeDescriptorProvider.GetHandlerTypeDescriptor(type)?.RequestProcessType ?? type.GetCustomAttributes(true) .Concat(@interface.GetCustomAttributes(true)) .OfType() diff --git a/src/JsonRpc/HandlerTypeDescriptorHelper.cs b/src/JsonRpc/HandlerTypeDescriptorProvider.cs similarity index 59% rename from src/JsonRpc/HandlerTypeDescriptorHelper.cs rename to src/JsonRpc/HandlerTypeDescriptorProvider.cs index 4ec3a65b3..c5d40d972 100644 --- a/src/JsonRpc/HandlerTypeDescriptorHelper.cs +++ b/src/JsonRpc/HandlerTypeDescriptorProvider.cs @@ -8,89 +8,17 @@ namespace OmniSharp.Extensions.JsonRpc { - public static class HandlerTypeDescriptorHelper + public interface IHandlerTypeDescriptorProvider where T : IHandlerTypeDescriptor { - private static readonly ConcurrentDictionary MethodNames = - new ConcurrentDictionary(); - - internal static readonly ILookup KnownHandlers; - - static HandlerTypeDescriptorHelper() - { - try - { - KnownHandlers = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany( - x => { - try - { - return x.GetTypes(); - } - catch - { - return Enumerable.Empty(); - } - } - ) - .Where(z => (z.IsInterface || (z.IsClass && !z.IsAbstract)) && typeof(IJsonRpcHandler).IsAssignableFrom(z)) - .Where(z => MethodAttribute.From(z) != null) - .Where(z => !z.Name.EndsWith("Manager")) // Manager interfaces are generally specializations around the handlers - .Select(GetMethodType) - .Distinct() - .ToLookup(x => MethodAttribute.From(x).Method) - .SelectMany(x => x.Select(z => new HandlerTypeDescriptor(z) as IHandlerTypeDescriptor)) - .ToLookup(x => x.Method, StringComparer.Ordinal); - } - catch (Exception e) - { - throw new AggregateException("Failed", e); - } - } - - public static IHandlerTypeDescriptor GetHandlerTypeDescriptor() => GetHandlerTypeDescriptor(typeof(T)); - - public static IHandlerTypeDescriptor GetHandlerTypeDescriptor(Type type) - { - var @default = KnownHandlers - .SelectMany(g => g) - .FirstOrDefault(x => x.InterfaceType == type || x.HandlerType == type || x.ParamsType == type); - if (@default != null) - { - return @default; - } - - var methodName = GetMethodName(type); - return string.IsNullOrWhiteSpace(methodName) ? null : KnownHandlers[methodName].FirstOrDefault(); - } - - public static string GetMethodName() where T : IJsonRpcHandler => GetMethodName(typeof(T)); - - public static bool IsMethodName(string name, params Type[] types) => types.Any(z => GetMethodName(z).Equals(name)); - - public static string GetMethodName(Type type) - { - if (MethodNames.TryGetValue(type, out var method)) return method; - - // Custom method - var attribute = MethodAttribute.From(type); - - var handler = KnownHandlers.SelectMany(z => z) - .FirstOrDefault(z => z.InterfaceType == type || z.HandlerType == type || z.ParamsType == type); - if (handler != null) - { - return handler.Method; - } - - // TODO: Log unknown method name - if (attribute is null) - { - return null; - } - - MethodNames.TryAdd(type, attribute.Method); - return attribute.Method; - } + T GetHandlerTypeDescriptor(); + T GetHandlerTypeDescriptor(Type type); + string GetMethodName() where T : IJsonRpcHandler; + bool IsMethodName(string name, params Type[] types); + string GetMethodName(Type type); + } + public class HandlerTypeDescriptorHelper + { internal static Type GetMethodType(Type type) { // Custom method @@ -138,11 +66,96 @@ public static Type GetHandlerInterface(Type type) } } - public static Type UnwrapGenericType(Type genericType, Type type) => + internal static Type UnwrapGenericType(Type genericType, Type type) => type?.GetTypeInfo() .ImplementedInterfaces .FirstOrDefault(x => x.GetTypeInfo().IsGenericType && x.GetTypeInfo().GetGenericTypeDefinition() == genericType) ?.GetTypeInfo() ?.GetGenericArguments()[0]; } + + class HandlerTypeDescriptorProvider : IHandlerTypeDescriptorProvider + { + private readonly ConcurrentDictionary MethodNames = + new ConcurrentDictionary(); + + internal readonly ILookup KnownHandlers; + + internal HandlerTypeDescriptorProvider(IEnumerable assemblies) + { + try + { + KnownHandlers = GetDescriptors(assemblies) + .ToLookup(x => x.Method, StringComparer.Ordinal); + } + catch (Exception e) + { + throw new AggregateException("Failed", e); + } + } + + internal static IEnumerable GetDescriptors(IEnumerable assemblies) => assemblies.SelectMany( + x => { + try + { + return x.GetTypes(); + } + catch + { + return Enumerable.Empty(); + } + } + ) + .Where(z => ( z.IsInterface || ( z.IsClass && !z.IsAbstract ) ) && typeof(IJsonRpcHandler).IsAssignableFrom(z)) + .Where(z => MethodAttribute.From(z) != null) + .Where(z => !z.Name.EndsWith("Manager")) // Manager interfaces are generally specializations around the handlers + .Select(HandlerTypeDescriptorHelper.GetMethodType) + .Distinct() + .ToLookup(x => MethodAttribute.From(x).Method) + .SelectMany(x => x.Select(z => new HandlerTypeDescriptor(z) as IHandlerTypeDescriptor)); + + public IHandlerTypeDescriptor GetHandlerTypeDescriptor() => GetHandlerTypeDescriptor(typeof(A)); + + public IHandlerTypeDescriptor GetHandlerTypeDescriptor(Type type) + { + var @default = KnownHandlers + .SelectMany(g => g) + .FirstOrDefault(x => x.InterfaceType == type || x.HandlerType == type || x.ParamsType == type); + if (@default != null) + { + return @default; + } + + var methodName = GetMethodName(type); + return string.IsNullOrWhiteSpace(methodName) ? null : KnownHandlers[methodName].FirstOrDefault(); + } + + public string GetMethodName() where T : IJsonRpcHandler => GetMethodName(typeof(T)); + + public bool IsMethodName(string name, params Type[] types) => types.Any(z => GetMethodName(z).Equals(name)); + + public string GetMethodName(Type type) + { + if (MethodNames.TryGetValue(type, out var method)) return method; + + // Custom method + var attribute = MethodAttribute.From(type); + + var handler = KnownHandlers.SelectMany(z => z) + .FirstOrDefault(z => z.InterfaceType == type || z.HandlerType == type || z.ParamsType == type); + if (handler != null) + { + return handler.Method; + } + + // TODO: Log unknown method name + if (attribute is null) + { + return null; + } + + MethodNames.TryAdd(type, attribute.Method); + return attribute.Method; + } + } } diff --git a/src/JsonRpc/JsonRpcServerOptionsBase.cs b/src/JsonRpc/JsonRpcServerOptionsBase.cs index 3760bc4f2..0af1e4efa 100644 --- a/src/JsonRpc/JsonRpcServerOptionsBase.cs +++ b/src/JsonRpc/JsonRpcServerOptionsBase.cs @@ -14,6 +14,10 @@ namespace OmniSharp.Extensions.JsonRpc { public abstract class JsonRpcServerOptionsBase : JsonRpcOptionsRegistryBase, IJsonRpcServerOptions where T : IJsonRpcHandlerRegistry { + protected JsonRpcServerOptionsBase() + { + WithAssemblies(typeof(JsonRpcServer).Assembly); + } public PipeReader Input { get; set; } public PipeWriter Output { get; set; } @@ -37,13 +41,13 @@ public ILoggerFactory LoggerFactory public T WithAssemblies(IEnumerable assemblies) { - Assemblies = Assemblies.Concat(assemblies); + Assemblies = Assemblies.Concat(assemblies ?? Enumerable.Empty()).ToArray(); return (T) (object) this; } public T WithAssemblies(params Assembly[] assemblies) { - Assemblies = Assemblies.Concat(assemblies); + Assemblies = Assemblies.Concat(assemblies).ToArray(); return (T) (object) this; } diff --git a/src/JsonRpc/JsonRpcServerServiceCollectionExtensions.cs b/src/JsonRpc/JsonRpcServerServiceCollectionExtensions.cs index 353be3cc9..f06115629 100644 --- a/src/JsonRpc/JsonRpcServerServiceCollectionExtensions.cs +++ b/src/JsonRpc/JsonRpcServerServiceCollectionExtensions.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.IO.Pipelines; using System.Linq; +using System.Reflection; using DryIoc; using MediatR; using Microsoft.Extensions.DependencyInjection; @@ -116,6 +118,7 @@ internal static IContainer AddJsonRpcServerInternals(this IContainer container, } container = container.AddJsonRpcServerCore(options); + container.RegisterInstanceMany(new HandlerTypeDescriptorProvider(options.Assemblies), nonPublicServiceTypes: true); container.RegisterInstance(options.Serializer ?? new JsonRpcSerializer()); container.RegisterInstance(options.Receiver); diff --git a/src/JsonRpc/ResponseRouter.cs b/src/JsonRpc/ResponseRouter.cs index 46f15d419..bd3244cf4 100644 --- a/src/JsonRpc/ResponseRouter.cs +++ b/src/JsonRpc/ResponseRouter.cs @@ -12,14 +12,16 @@ public class ResponseRouter : IResponseRouter { internal readonly IOutputHandler OutputHandler; internal readonly ISerializer Serializer; + private readonly IHandlerTypeDescriptorProvider _handlerTypeDescriptorProvider; internal readonly ConcurrentDictionary pendingTask)> Requests = new ConcurrentDictionary pendingTask)>(); - public ResponseRouter(IOutputHandler outputHandler, ISerializer serializer) + public ResponseRouter(IOutputHandler outputHandler, ISerializer serializer, IHandlerTypeDescriptorProvider handlerTypeDescriptorProvider) { OutputHandler = outputHandler; Serializer = serializer; + _handlerTypeDescriptorProvider = handlerTypeDescriptorProvider; } public void SendNotification(string method) => @@ -53,7 +55,7 @@ public Task SendRequest(IRequest @params, Cance } private string GetMethodName(Type type) => - HandlerTypeDescriptorHelper.GetMethodName(type) ?? throw new NotSupportedException($"Unable to infer method name for type {type.FullName}"); + _handlerTypeDescriptorProvider.GetMethodName(type) ?? throw new NotSupportedException($"Unable to infer method name for type {type.FullName}"); private class ResponseRouterReturnsImpl : IResponseRouterReturns { diff --git a/src/Protocol/LanguageProtocolRpcOptionsBase.cs b/src/Protocol/LanguageProtocolRpcOptionsBase.cs index 986065112..a4f21da7d 100644 --- a/src/Protocol/LanguageProtocolRpcOptionsBase.cs +++ b/src/Protocol/LanguageProtocolRpcOptionsBase.cs @@ -12,7 +12,11 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol { public abstract class LanguageProtocolRpcOptionsBase : JsonRpcServerOptionsBase where T : IJsonRpcHandlerRegistry { - public LanguageProtocolRpcOptionsBase() => Services.AddLogging(builder => LoggingBuilderAction?.Invoke(builder)); + public LanguageProtocolRpcOptionsBase() + { + Services.AddLogging(builder => LoggingBuilderAction?.Invoke(builder)); + WithAssemblies(typeof(LanguageProtocolRpcOptionsBase<>).Assembly); + } public T AddTextDocumentIdentifier(params ITextDocumentIdentifier[] handlers) { diff --git a/src/Protocol/Shared/LspHandlerTypeDescriptorHelper.cs b/src/Protocol/Shared/LspHandlerTypeDescriptorHelper.cs deleted file mode 100644 index fd25d4852..000000000 --- a/src/Protocol/Shared/LspHandlerTypeDescriptorHelper.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Shared -{ - public static class LspHandlerTypeDescriptorHelper - { - private static readonly ConcurrentDictionary MethodNames = - new ConcurrentDictionary(); - - private static readonly ILookup KnownHandlers; - - static LspHandlerTypeDescriptorHelper() - { - try - { - KnownHandlers = HandlerTypeDescriptorHelper.KnownHandlers.SelectMany(x => x) - .Select(x => new LspHandlerTypeDescriptor(x.HandlerType) as ILspHandlerTypeDescriptor) - .ToLookup(x => x.Method, x => x, StringComparer.Ordinal); - } - catch (Exception e) - { - throw new AggregateException("Failed", e); - } - } - - public static string GetMethodForRegistrationOptions(object registrationOptions) - { - var registrationType = registrationOptions.GetType(); - var interfaces = new HashSet( - registrationOptions.GetType().GetInterfaces() - .Except(registrationType.BaseType?.GetInterfaces() ?? Enumerable.Empty()) - ); - return interfaces.SelectMany( - x => - KnownHandlers.SelectMany(z => z) - .Where(z => z.HasRegistration) - .Where(z => x.IsAssignableFrom(z.RegistrationType)) - ) - .FirstOrDefault()?.Method; - } - - public static Type GetRegistrationType(string method) => KnownHandlers[method] - .Where(z => z.HasRegistration) - .Select(z => z.RegistrationType) - .FirstOrDefault(); - public static ILspHandlerTypeDescriptor GetHandlerTypeDescriptor() => GetHandlerTypeDescriptor(typeof(T)); - - public static ILspHandlerTypeDescriptor GetHandlerTypeDescriptor(Type type) - { - var @default = KnownHandlers - .SelectMany(g => g) - .FirstOrDefault(x => x.InterfaceType == type || x.HandlerType == type || x.ParamsType == type) - ?? KnownHandlers - .SelectMany(g => g) - .FirstOrDefault(x => x.InterfaceType.IsAssignableFrom(type) || x.HandlerType.IsAssignableFrom(type)); - if (@default != null) - { - return @default; - } - - var methodName = HandlerTypeDescriptorHelper.GetMethodName(type); - return string.IsNullOrWhiteSpace(methodName) ? null : KnownHandlers[methodName].FirstOrDefault(); - } - } -} diff --git a/src/Protocol/Shared/LspHandlerTypeDescriptorProvider.cs b/src/Protocol/Shared/LspHandlerTypeDescriptorProvider.cs new file mode 100644 index 000000000..749fb3913 --- /dev/null +++ b/src/Protocol/Shared/LspHandlerTypeDescriptorProvider.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using OmniSharp.Extensions.JsonRpc; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Shared +{ + public interface ILspHandlerTypeDescriptorProvider : IHandlerTypeDescriptorProvider + { + string GetMethodForRegistrationOptions(object registrationOptions); + Type GetRegistrationType(string method); + } + + public class LspHandlerTypeDescriptorProvider : ILspHandlerTypeDescriptorProvider, IHandlerTypeDescriptorProvider + { + private readonly ConcurrentDictionary MethodNames = new ConcurrentDictionary(); + + private readonly ILookup KnownHandlers; + + internal LspHandlerTypeDescriptorProvider(IEnumerable assemblies) + { + KnownHandlers = HandlerTypeDescriptorProvider + .GetDescriptors(assemblies) + .Select(x => new LspHandlerTypeDescriptor(x.HandlerType) as ILspHandlerTypeDescriptor) + .ToLookup(x => x.Method, x => x, StringComparer.Ordinal); + } + + public string GetMethodForRegistrationOptions(object registrationOptions) + { + var registrationType = registrationOptions.GetType(); + var interfaces = new HashSet( + registrationOptions.GetType().GetInterfaces() + .Except(registrationType.BaseType?.GetInterfaces() ?? Enumerable.Empty()) + ); + return interfaces.SelectMany( + x => + KnownHandlers.SelectMany(z => z) + .Where(z => z.HasRegistration) + .Where(z => x.IsAssignableFrom(z.RegistrationType)) + ) + .FirstOrDefault()?.Method; + } + + public Type GetRegistrationType(string method) => KnownHandlers[method] + .Where(z => z.HasRegistration) + .Select(z => z.RegistrationType) + .FirstOrDefault(); + + public ILspHandlerTypeDescriptor GetHandlerTypeDescriptor() => GetHandlerTypeDescriptor(typeof(A)); + IHandlerTypeDescriptor IHandlerTypeDescriptorProvider.GetHandlerTypeDescriptor(Type type) => GetHandlerTypeDescriptor(type); + + IHandlerTypeDescriptor IHandlerTypeDescriptorProvider.GetHandlerTypeDescriptor() => GetHandlerTypeDescriptor(); + + public ILspHandlerTypeDescriptor GetHandlerTypeDescriptor(Type type) + { + var @default = KnownHandlers + .SelectMany(g => g) + .FirstOrDefault(x => x.InterfaceType == type || x.HandlerType == type || x.ParamsType == type) + ?? KnownHandlers + .SelectMany(g => g) + .FirstOrDefault(x => x.InterfaceType.IsAssignableFrom(type) || x.HandlerType.IsAssignableFrom(type)); + if (@default != null) + { + return @default; + } + + var methodName = GetMethodName(type); + return string.IsNullOrWhiteSpace(methodName) ? null : KnownHandlers[methodName].FirstOrDefault(); + } + + public string GetMethodName() where T : IJsonRpcHandler => GetMethodName(typeof(T)); + + public bool IsMethodName(string name, params Type[] types) => types.Any(z => GetMethodName(z).Equals(name)); + + public string GetMethodName(Type type) + { + if (MethodNames.TryGetValue(type, out var method)) return method; + + // Custom method + var attribute = MethodAttribute.From(type); + + var handler = KnownHandlers.SelectMany(z => z) + .FirstOrDefault(z => z.InterfaceType == type || z.HandlerType == type || z.ParamsType == type); + if (handler != null) + { + return handler.Method; + } + + // TODO: Log unknown method name + if (attribute is null) + { + return null; + } + + MethodNames.TryAdd(type, attribute.Method); + return attribute.Method; + } + } +} diff --git a/src/Server/LanguageServerOptions.cs b/src/Server/LanguageServerOptions.cs index cbef2eff2..ab6eeede3 100644 --- a/src/Server/LanguageServerOptions.cs +++ b/src/Server/LanguageServerOptions.cs @@ -6,19 +6,17 @@ using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Shared; namespace OmniSharp.Extensions.LanguageServer.Server { public class LanguageServerOptions : LanguageProtocolRpcOptionsBase, ILanguageServerRegistry { - public ServerInfo ServerInfo { get; set; } - public ILspServerReceiver Receiver { get; set; } = new LspServerReceiver(); - - public LanguageServerOptions WithReceiver(ILspServerReceiver receiver) + public LanguageServerOptions() { - Receiver = receiver; - return this; + WithAssemblies(typeof(LanguageServerOptions).Assembly, typeof(LspRequestRouter).Assembly); } + public ServerInfo ServerInfo { get; set; } ILanguageServerRegistry IJsonRpcHandlerRegistry.AddHandler(string method, IJsonRpcHandler handler, JsonRpcHandlerOptions options) => AddHandler(method, handler, options); diff --git a/src/Server/LanguageServerOptionsExtensions.cs b/src/Server/LanguageServerOptionsExtensions.cs index 7afaa320f..0b7a18d4e 100644 --- a/src/Server/LanguageServerOptionsExtensions.cs +++ b/src/Server/LanguageServerOptionsExtensions.cs @@ -23,6 +23,15 @@ public static LanguageServerOptions WithSerializer(this LanguageServerOptions op return options; } + public static LanguageServerOptions WithReceiver( + this LanguageServerOptions options, + ILspServerReceiver serverReceiver + ) + { + options.Services.AddSingleton(serverReceiver); + return options; + } + public static LanguageServerOptions WithServerInfo(this LanguageServerOptions options, ServerInfo serverInfo) { options.ServerInfo = serverInfo; diff --git a/src/Server/LanguageServerServiceCollectionExtensions.cs b/src/Server/LanguageServerServiceCollectionExtensions.cs index e14e164eb..fa5746b70 100644 --- a/src/Server/LanguageServerServiceCollectionExtensions.cs +++ b/src/Server/LanguageServerServiceCollectionExtensions.cs @@ -22,14 +22,13 @@ public static class LanguageServerServiceCollectionExtensions { internal static IContainer AddLanguageServerInternals(this IContainer container, LanguageServerOptions options, IServiceProvider outerServiceProvider) { - if (options.Receiver == null) - { - throw new ArgumentException("Receiver is missing!", nameof(options)); - } - container = container.AddLanguageProtocolInternals(options); + container.RegisterMany( + reuse: Reuse.Singleton, + nonPublicServiceTypes: true, + ifAlreadyRegistered: IfAlreadyRegistered.Keep + ); - container.RegisterInstanceMany(options.Receiver); if (options.OnUnhandledException != null) { container.RegisterInstance(options.OnUnhandledException); diff --git a/src/Server/LspServerReceiver.cs b/src/Server/LspServerReceiver.cs index 25a218706..744490293 100644 --- a/src/Server/LspServerReceiver.cs +++ b/src/Server/LspServerReceiver.cs @@ -5,14 +5,21 @@ using OmniSharp.Extensions.JsonRpc.Server; using OmniSharp.Extensions.LanguageServer.Protocol.General; using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Shared; using OmniSharp.Extensions.LanguageServer.Server.Messages; namespace OmniSharp.Extensions.LanguageServer.Server { public class LspServerReceiver : Receiver, ILspServerReceiver { + private readonly ILspHandlerTypeDescriptorProvider _handlerTypeDescriptorProvider; private bool _initialized; + public LspServerReceiver(ILspHandlerTypeDescriptorProvider handlerTypeDescriptorProvider) + { + _handlerTypeDescriptorProvider = handlerTypeDescriptorProvider; + } + public override (IEnumerable results, bool hasResponse) GetRequests(JToken container) { if (_initialized) return base.GetRequests(container); @@ -23,7 +30,7 @@ public override (IEnumerable results, bool hasResponse) GetRequests(JToke var (results, hasResponse) = base.GetRequests(container); foreach (var item in results) { - if (item.IsRequest && HandlerTypeDescriptorHelper.IsMethodName(item.Request.Method, typeof(ILanguageProtocolInitializeHandler))) + if (item.IsRequest && _handlerTypeDescriptorProvider.IsMethodName(item.Request.Method, typeof(ILanguageProtocolInitializeHandler))) { newResults.Add(item); } diff --git a/src/Server/Server.csproj b/src/Server/Server.csproj index 239553952..f7c843a24 100644 --- a/src/Server/Server.csproj +++ b/src/Server/Server.csproj @@ -13,8 +13,4 @@ - - - - diff --git a/src/Shared/LanguageProtocolServiceCollectionExtensions.cs b/src/Shared/LanguageProtocolServiceCollectionExtensions.cs index c3d1b301f..c3e4ddf53 100644 --- a/src/Shared/LanguageProtocolServiceCollectionExtensions.cs +++ b/src/Shared/LanguageProtocolServiceCollectionExtensions.cs @@ -1,11 +1,14 @@ using System; +using System.Collections.Generic; using System.Linq; +using System.Reflection; using DryIoc; using Microsoft.Extensions.DependencyInjection; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Shared; namespace OmniSharp.Extensions.LanguageServer.Shared { @@ -23,6 +26,7 @@ internal static IContainer AddLanguageProtocolInternals(this IContainer conta } container = container.AddJsonRpcServerCore(options); + container.RegisterInstanceMany(new LspHandlerTypeDescriptorProvider(options.Assemblies), nonPublicServiceTypes: true); container.RegisterInstanceMany(options.Serializer); container.RegisterInstance(options.RequestProcessIdentifier); diff --git a/src/Shared/RequestProcessIdentifier.cs b/src/Shared/RequestProcessIdentifier.cs index 5319dab35..339eb253b 100644 --- a/src/Shared/RequestProcessIdentifier.cs +++ b/src/Shared/RequestProcessIdentifier.cs @@ -24,24 +24,17 @@ public RequestProcessType Identify(IHandlerDescriptor descriptor) if (_cache.TryGetValue(descriptor.HandlerType, out var type)) return type; type = _defaultRequestProcessType; - var typeDescriptor = HandlerTypeDescriptorHelper.GetHandlerTypeDescriptor(descriptor.HandlerType); - if (typeDescriptor?.RequestProcessType.HasValue == true) + var processAttribute = descriptor.ImplementationType + .GetCustomAttributes(true) + .Concat(descriptor.HandlerType.GetCustomAttributes(true)) + .OfType() + .FirstOrDefault(); + if (processAttribute != null) { - type = typeDescriptor.RequestProcessType.Value; - } - else - { - var processAttribute = descriptor.ImplementationType - .GetCustomAttributes(true) - .Concat(descriptor.HandlerType.GetCustomAttributes(true)) - .OfType() - .FirstOrDefault(); - if (processAttribute != null) - { - type = processAttribute.Type; - } + type = processAttribute.Type; } + _cache.TryAdd(descriptor.HandlerType, type); return type; diff --git a/src/Shared/SharedHandlerCollection.cs b/src/Shared/SharedHandlerCollection.cs index 1002c2a61..7a600383d 100644 --- a/src/Shared/SharedHandlerCollection.cs +++ b/src/Shared/SharedHandlerCollection.cs @@ -25,12 +25,18 @@ internal class SharedHandlerCollection : IHandlerCollection private readonly TextDocumentIdentifiers _textDocumentIdentifiers; private ImmutableHashSet _descriptors = ImmutableHashSet.Empty; private readonly IServiceProvider _serviceProvider; + private readonly ILspHandlerTypeDescriptorProvider _handlerTypeDescriptorProvider; - public SharedHandlerCollection(ISupportedCapabilities supportedCapabilities, TextDocumentIdentifiers textDocumentIdentifiers, IServiceProvider serviceProvider) + public SharedHandlerCollection( + ISupportedCapabilities supportedCapabilities, + TextDocumentIdentifiers textDocumentIdentifiers, + IServiceProvider serviceProvider, + ILspHandlerTypeDescriptorProvider handlerTypeDescriptorProvider) { _supportedCapabilities = supportedCapabilities; _textDocumentIdentifiers = textDocumentIdentifiers; _serviceProvider = serviceProvider; + _handlerTypeDescriptorProvider = handlerTypeDescriptorProvider; } public IEnumerator GetEnumerator() => _descriptors.GetEnumerator(); @@ -188,7 +194,7 @@ JsonRpcHandlerOptions options var cd = new CompositeDisposable(); foreach (var (method, implementedInterface) in handler.GetType().GetTypeInfo() .ImplementedInterfaces - .Select(x => ( method: HandlerTypeDescriptorHelper.GetMethodName(x), implementedInterface: x )) + .Select(x => ( method: _handlerTypeDescriptorProvider.GetMethodName(x), implementedInterface: x )) .Distinct(new EqualityComparer()) .Where(x => !string.IsNullOrWhiteSpace(x.method)) ) @@ -215,7 +221,7 @@ private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, ISer private LspHandlerDescriptor GetDescriptor(string method, Type handlerType, IJsonRpcHandler handler, JsonRpcHandlerOptions options) { - var typeDescriptor = LspHandlerTypeDescriptorHelper.GetHandlerTypeDescriptor(handlerType); + var typeDescriptor = _handlerTypeDescriptorProvider.GetHandlerTypeDescriptor(handlerType); var @interface = HandlerTypeDescriptorHelper.GetHandlerInterface(handlerType); var registrationType = typeDescriptor?.RegistrationType ?? HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handlerType); diff --git a/src/Testing/LanguageProtocolTestBase.cs b/src/Testing/LanguageProtocolTestBase.cs index 02c44dd5b..3b1322a99 100644 --- a/src/Testing/LanguageProtocolTestBase.cs +++ b/src/Testing/LanguageProtocolTestBase.cs @@ -46,7 +46,9 @@ Action serverOptionsAction options => { options .WithLoggerFactory(TestOptions.ClientLoggerFactory) + .WithAssemblies(TestOptions.Assemblies) .ConfigureLogging(x => x.SetMinimumLevel(LogLevel.Trace)) + .WithAssemblies(typeof(LanguageProtocolTestBase).Assembly, GetType().Assembly) .Services .AddTransient(typeof(IPipelineBehavior<,>), typeof(SettlePipeline<,>)) .AddSingleton(ClientEvents as IRequestSettler); @@ -59,7 +61,9 @@ Action serverOptionsAction options => { options .WithLoggerFactory(TestOptions.ClientLoggerFactory) + .WithAssemblies(TestOptions.Assemblies) .ConfigureLogging(x => x.SetMinimumLevel(LogLevel.Trace)) + .WithAssemblies(typeof(LanguageProtocolTestBase).Assembly, GetType().Assembly) .Services .AddTransient(typeof(IPipelineBehavior<,>), typeof(SettlePipeline<,>)) .AddSingleton(ServerEvents as IRequestSettler); diff --git a/src/Testing/LanguageServerTestBase.cs b/src/Testing/LanguageServerTestBase.cs index 61bf4578a..a556cea53 100644 --- a/src/Testing/LanguageServerTestBase.cs +++ b/src/Testing/LanguageServerTestBase.cs @@ -33,6 +33,8 @@ protected virtual ILanguageClient CreateClient(Action cli .WithInput(reader) .WithOutput(writer) .WithLoggerFactory(TestOptions.ClientLoggerFactory) + .WithAssemblies(TestOptions.Assemblies) + .WithAssemblies(typeof(LanguageProtocolTestBase).Assembly, GetType().Assembly) .ConfigureLogging(x => x.SetMinimumLevel(LogLevel.Trace)) .Services .AddTransient(typeof(IPipelineBehavior<,>), typeof(SettlePipeline<,>)) diff --git a/test/Dap.Tests/FoundationTests.cs b/test/Dap.Tests/FoundationTests.cs index a283f6557..18b9fa1ea 100644 --- a/test/Dap.Tests/FoundationTests.cs +++ b/test/Dap.Tests/FoundationTests.cs @@ -12,9 +12,11 @@ using Microsoft.Extensions.Logging; using NSubstitute; using OmniSharp.Extensions.DebugAdapter.Client; +using OmniSharp.Extensions.DebugAdapter.Protocol; using OmniSharp.Extensions.DebugAdapter.Protocol.Events; using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; using OmniSharp.Extensions.DebugAdapter.Server; +using OmniSharp.Extensions.DebugAdapter.Testing; using OmniSharp.Extensions.JsonRpc; using Xunit; using Xunit.Abstractions; @@ -458,6 +460,15 @@ public class TypeHandlerData : TheoryData { public TypeHandlerData() { + var handlerTypeDescriptorProvider = new HandlerTypeDescriptorProvider(new[] { + + typeof(HandlerTypeDescriptorProvider).Assembly, + typeof(DebugAdapterRpcOptionsBase<>).Assembly, + typeof(DebugAdapterClient).Assembly, + typeof(DebugAdapterServer).Assembly, + typeof(DapReceiver).Assembly, + typeof(DebugAdapterProtocolTestBase).Assembly + }); foreach (var type in typeof(CompletionsArguments).Assembly.ExportedTypes.Where( z => z.IsInterface && typeof(IJsonRpcHandler).IsAssignableFrom(z) )) @@ -465,7 +476,7 @@ public TypeHandlerData() if (type.IsGenericTypeDefinition && !MethodAttribute.AllFrom(type).Any()) continue; if (type == typeof(IProgressStartHandler) || type == typeof(IProgressUpdateHandler) || type == typeof(IProgressEndHandler)) continue; - Add(HandlerTypeDescriptorHelper.GetHandlerTypeDescriptor(type)); + Add(handlerTypeDescriptorProvider.GetHandlerTypeDescriptor(type)); } } } @@ -474,12 +485,20 @@ public class TypeHandlerExtensionData : TheoryData).Assembly, + typeof(DebugAdapterClient).Assembly, + typeof(DebugAdapterServer).Assembly, + typeof(DapReceiver).Assembly, + typeof(DebugAdapterProtocolTestBase).Assembly + }); foreach (var type in typeof(CompletionsArguments).Assembly.ExportedTypes .Where(z => z.IsInterface && typeof(IJsonRpcHandler).IsAssignableFrom(z))) { if (type.IsGenericTypeDefinition && !MethodAttribute.AllFrom(type).Any()) continue; if (type == typeof(IProgressStartHandler) || type == typeof(IProgressUpdateHandler) || type == typeof(IProgressEndHandler)) continue; - var descriptor = HandlerTypeDescriptorHelper.GetHandlerTypeDescriptor(type); + var descriptor = handlerTypeDescriptorProvider.GetHandlerTypeDescriptor(type); Add( descriptor, diff --git a/test/JsonRpc.Tests/HandlerResolverTests.cs b/test/JsonRpc.Tests/HandlerResolverTests.cs index 388ef54f0..d5298532a 100644 --- a/test/JsonRpc.Tests/HandlerResolverTests.cs +++ b/test/JsonRpc.Tests/HandlerResolverTests.cs @@ -51,7 +51,7 @@ public interface IInlineJsonRpcNotificationHandler : IJsonRpcNotificationHandler [InlineData(typeof(IInlineJsonRpcNotificationHandler), "notification")] public void Should_Contain_AllDefinedMethods(Type requestHandler, string key) { - var handler = new HandlerCollection(new ServiceCollection().BuildServiceProvider()) { + var handler = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })) { (IJsonRpcHandler) Substitute.For(new[] { requestHandler }, new object[0]) }; handler.Should().Contain(x => x.Method == key); @@ -64,7 +64,7 @@ public void Should_Contain_AllDefinedMethods(Type requestHandler, string key) [InlineData(typeof(IInlineJsonRpcNotificationHandler), "notification", null)] public void Should_Have_CorrectParams(Type requestHandler, string key, Type expected) { - var handler = new HandlerCollection(new ServiceCollection().BuildServiceProvider()) { + var handler = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })) { (IJsonRpcHandler) Substitute.For(new[] { requestHandler }, new object[0]) }; handler.First(x => x.Method == key).Params.Should().IsSameOrEqualTo(expected); diff --git a/test/JsonRpc.Tests/MediatorTestsNotificationHandler.cs b/test/JsonRpc.Tests/MediatorTestsNotificationHandler.cs index 75bb09c61..52ba74d52 100644 --- a/test/JsonRpc.Tests/MediatorTestsNotificationHandler.cs +++ b/test/JsonRpc.Tests/MediatorTestsNotificationHandler.cs @@ -23,7 +23,7 @@ public async Task ExecutesHandler() { var exitHandler = Substitute.For(); - var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider()) { exitHandler }; + var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })) { exitHandler }; AutoSubstitute.Provide(collection); var router = AutoSubstitute.Resolve(); diff --git a/test/JsonRpc.Tests/MediatorTestsNotificationHandlerOfT.cs b/test/JsonRpc.Tests/MediatorTestsNotificationHandlerOfT.cs index 02627472d..a4aa9ac38 100644 --- a/test/JsonRpc.Tests/MediatorTestsNotificationHandlerOfT.cs +++ b/test/JsonRpc.Tests/MediatorTestsNotificationHandlerOfT.cs @@ -33,7 +33,7 @@ public async Task ExecutesHandler() var cancelRequestHandler = Substitute.For(); var mediator = Substitute.For(); - var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider()) { cancelRequestHandler }; + var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })) { cancelRequestHandler }; AutoSubstitute.Provide(collection); var router = AutoSubstitute.Resolve(); diff --git a/test/JsonRpc.Tests/MediatorTestsRequestHandlerOfTRequest.cs b/test/JsonRpc.Tests/MediatorTestsRequestHandlerOfTRequest.cs index 325863e15..26e5bfdae 100644 --- a/test/JsonRpc.Tests/MediatorTestsRequestHandlerOfTRequest.cs +++ b/test/JsonRpc.Tests/MediatorTestsRequestHandlerOfTRequest.cs @@ -33,7 +33,7 @@ public async Task ExecutesHandler() var executeCommandHandler = Substitute.For(); var mediator = Substitute.For(); - var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider()) { executeCommandHandler }; + var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })) { executeCommandHandler }; AutoSubstitute.Provide(collection); var router = AutoSubstitute.Resolve(); diff --git a/test/JsonRpc.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs b/test/JsonRpc.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs index 11933942a..fcd1343f0 100644 --- a/test/JsonRpc.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs +++ b/test/JsonRpc.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs @@ -43,7 +43,7 @@ public async Task ExecutesHandler() var codeActionHandler = Substitute.For(); var mediator = Substitute.For(); - var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider()) { codeActionHandler }; + var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })) { codeActionHandler }; AutoSubstitute.Provide(collection); var router = AutoSubstitute.Resolve(); diff --git a/test/JsonRpc.Tests/RequestRouterTests.cs b/test/JsonRpc.Tests/RequestRouterTests.cs index b67382d74..49765cec4 100644 --- a/test/JsonRpc.Tests/RequestRouterTests.cs +++ b/test/JsonRpc.Tests/RequestRouterTests.cs @@ -18,7 +18,7 @@ public class RequestRouterTests : AutoTestBase [Fact] public async Task ShouldRoute_CustomRequestResponse() { - var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider()); + var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })); var registry = new TestLanguageServerRegistry(); AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -38,7 +38,7 @@ public async Task ShouldRoute_CustomRequestResponse() [Fact] public async Task ShouldRoute_CustomRequest() { - var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider()); + var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })); var registry = new TestLanguageServerRegistry(); AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -58,7 +58,7 @@ public async Task ShouldRoute_CustomRequest() [Fact] public async Task ShouldRoute_CustomNotification() { - var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider()); + var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })); var registry = new TestLanguageServerRegistry(); AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -77,7 +77,7 @@ public async Task ShouldRoute_CustomNotification() [Fact] public async Task ShouldRoute_CustomEmptyNotification() { - var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider()); + var collection = new HandlerCollection(new ServiceCollection().BuildServiceProvider(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })); var registry = new TestLanguageServerRegistry(); AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); diff --git a/test/JsonRpc.Tests/ResponseRouterTests.cs b/test/JsonRpc.Tests/ResponseRouterTests.cs index 18a654e23..ecb84b685 100644 --- a/test/JsonRpc.Tests/ResponseRouterTests.cs +++ b/test/JsonRpc.Tests/ResponseRouterTests.cs @@ -18,7 +18,7 @@ public class ResponseRouterTests public async Task WorksWithResultType() { var outputHandler = Substitute.For(); - var router = new ResponseRouter(outputHandler, new JsonRpcSerializer()); + var router = new ResponseRouter(outputHandler, new JsonRpcSerializer(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })); outputHandler .When(x => x.Send(Arg.Is(x => x.GetType() == typeof(OutgoingRequest)))) @@ -42,7 +42,7 @@ public async Task WorksWithResultType() public async Task WorksWithUnitType() { var outputHandler = Substitute.For(); - var router = new ResponseRouter(outputHandler, new JsonRpcSerializer()); + var router = new ResponseRouter(outputHandler, new JsonRpcSerializer(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })); outputHandler .When(x => x.Send(Arg.Is(x => x.GetType() == typeof(OutgoingRequest)))) @@ -63,7 +63,7 @@ public async Task WorksWithUnitType() public async Task WorksWithNotification() { var outputHandler = Substitute.For(); - var router = new ResponseRouter(outputHandler, new JsonRpcSerializer()); + var router = new ResponseRouter(outputHandler, new JsonRpcSerializer(), new HandlerTypeDescriptorProvider(new [] { typeof(HandlerTypeDescriptorProvider).Assembly, typeof(HandlerResolverTests).Assembly })); router.SendNotification(new NotificationParams()); diff --git a/test/Lsp.Tests/ClientCapabilityProviderFixture.cs b/test/Lsp.Tests/ClientCapabilityProviderFixture.cs index e05dc1ddc..c1b583b00 100644 --- a/test/Lsp.Tests/ClientCapabilityProviderFixture.cs +++ b/test/Lsp.Tests/ClientCapabilityProviderFixture.cs @@ -1,9 +1,11 @@ using Microsoft.Extensions.DependencyInjection; using NSubstitute; +using OmniSharp.Extensions.LanguageServer.Client; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Shared; using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; using OmniSharp.Extensions.LanguageServer.Server; using OmniSharp.Extensions.LanguageServer.Shared; @@ -20,7 +22,10 @@ public ClientCapabilityProviderFixture() handler.GetRegistrationOptions().Returns(new ExecuteCommandRegistrationOptions()); var handlerCollection = new SharedHandlerCollection( - SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider() + SupportedCapabilitiesFixture.AlwaysTrue, + new TextDocumentIdentifiers(), + new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly }) ) { handler }; var capabilityProvider = new ClientCapabilityProvider(handlerCollection, true); diff --git a/test/Lsp.Tests/ClientCapabilityProviderTests.cs b/test/Lsp.Tests/ClientCapabilityProviderTests.cs index b2dcd7a9f..f9b50b05b 100644 --- a/test/Lsp.Tests/ClientCapabilityProviderTests.cs +++ b/test/Lsp.Tests/ClientCapabilityProviderTests.cs @@ -6,11 +6,13 @@ using Microsoft.Extensions.DependencyInjection; using NSubstitute; using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Client; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Shared; using OmniSharp.Extensions.LanguageServer.Server; using OmniSharp.Extensions.LanguageServer.Shared; using Xunit; @@ -36,7 +38,8 @@ public void Should_AllowSupportedCapabilities(IJsonRpcHandler handler, object in TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler, handler }; var provider = new ClientCapabilityProvider(collection, true); @@ -66,7 +69,8 @@ public void Should_AllowUnsupportedCapabilities(IJsonRpcHandler handler, object TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler, handler }; var provider = new ClientCapabilityProvider(collection, true); @@ -119,7 +123,8 @@ public void Should_AllowNullSupportedCapabilities(IJsonRpcHandler handler, objec TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler, handler }; var provider = new ClientCapabilityProvider(collection, true); @@ -144,7 +149,8 @@ public void Should_DisallowDynamicSupportedCapabilities(IJsonRpcHandler handler, TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler, handler }; var provider = new ClientCapabilityProvider(collection, true); @@ -174,7 +180,8 @@ public void Should_Handle_Mixed_Capabilities() var typeDefinitionHandler = Substitute.For(); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler, codeActionHandler, definitionHandler, typeDefinitionHandler }; var provider = new ClientCapabilityProvider(collection, true); var capabilities = new ClientCapabilities { @@ -205,7 +212,8 @@ public void GH162_TextDocumentSync_Should_Work_Without_WillSave_Or_WillSaveWaitU TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler }; var provider = new ClientCapabilityProvider(collection, true); var capabilities = new ClientCapabilities { @@ -232,7 +240,8 @@ public void GH162_TextDocumentSync_Should_Work_With_WillSave_Or_WillSaveWaitUnti var didSaveTextDocumentHandler = Substitute.For(); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) { + new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler, willSaveTextDocumentHandler, willSaveWaitUntilTextDocumentHandler, didSaveTextDocumentHandler }; diff --git a/test/Lsp.Tests/FoundationTests.cs b/test/Lsp.Tests/FoundationTests.cs index cfd5fec46..08eceeee5 100644 --- a/test/Lsp.Tests/FoundationTests.cs +++ b/test/Lsp.Tests/FoundationTests.cs @@ -15,6 +15,7 @@ using NSubstitute.Core; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Client; +using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; @@ -633,13 +634,22 @@ public class TypeHandlerData : TheoryData { public TypeHandlerData() { + var handlerTypeDescriptorProvider = + new LspHandlerTypeDescriptorProvider(new[] { + typeof(HandlerTypeDescriptorProvider).Assembly, + typeof(LspHandlerTypeDescriptorProvider).Assembly, + typeof(LanguageServer).Assembly, + typeof(LanguageClient).Assembly, + typeof(ISupports).Assembly, + typeof(HandlerResolverTests).Assembly + }); foreach (var type in typeof(CompletionParams).Assembly.ExportedTypes.Where(z => z.IsInterface && typeof(IJsonRpcHandler).IsAssignableFrom(z)) .Where(z => !z.Name.EndsWith("Manager")) .Except(new[] { typeof(ITextDocumentSyncHandler) }) ) { if (type.IsGenericTypeDefinition && !MethodAttribute.AllFrom(type).Any()) continue; - Add(LspHandlerTypeDescriptorHelper.GetHandlerTypeDescriptor(type)); + Add(handlerTypeDescriptorProvider.GetHandlerTypeDescriptor(type)); } } } @@ -654,6 +664,15 @@ public class TypeHandlerExtensionData : TheoryData z.IsInterface && typeof(IJsonRpcHandler).IsAssignableFrom(z)) .Where(z => !z.Name.EndsWith("Manager")) @@ -664,7 +683,7 @@ public TypeHandlerExtensionData() if (type.Name.EndsWith("Manager")) continue; if (type == typeof(ICompletionResolveHandler) || type == typeof(ICodeLensResolveHandler) || type == typeof(IDocumentLinkResolveHandler)) continue; if (type == typeof(ISemanticTokensHandler) || type == typeof(ISemanticTokensDeltaHandler) || type == typeof(ISemanticTokensRangeHandler)) continue; - var descriptor = LspHandlerTypeDescriptorHelper.GetHandlerTypeDescriptor(type); + var descriptor = handlerTypeDescriptorProvider.GetHandlerTypeDescriptor(type); if (descriptor == null) { diff --git a/test/Lsp.Tests/HandlerResolverTests.cs b/test/Lsp.Tests/HandlerResolverTests.cs index a11e24f9c..f01e11adc 100644 --- a/test/Lsp.Tests/HandlerResolverTests.cs +++ b/test/Lsp.Tests/HandlerResolverTests.cs @@ -6,11 +6,13 @@ using Microsoft.Extensions.DependencyInjection; using NSubstitute; using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Client; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.General; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Shared; +using OmniSharp.Extensions.LanguageServer.Server; using OmniSharp.Extensions.LanguageServer.Shared; using Xunit; @@ -25,7 +27,8 @@ public class HandlerResolverTests [InlineData(typeof(IExitHandler), "exit", 1)] public void Should_Contain_AllDefinedMethods(Type requestHandler, string key, int count) { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); var sub = (IJsonRpcHandler) Substitute.For(new[] { requestHandler }, new object[0]); handler.Add(sub); @@ -36,7 +39,8 @@ public void Should_Contain_AllDefinedMethods(Type requestHandler, string key, in [Fact] public void Should_Contain_AllConcreteDefinedMethods() { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); handler.Add( Substitute.For(), @@ -57,7 +61,8 @@ public void Should_Contain_AllConcreteDefinedMethods() [InlineData(TextDocumentNames.DidSave, 4)] public void Should_Contain_AllDefinedTextDocumentSyncMethods(string key, int count) { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); var sub = (IJsonRpcHandler) TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.something"), "csharp"); handler.Add(sub); @@ -72,7 +77,8 @@ public void Should_Contain_AllDefinedTextDocumentSyncMethods(string key, int cou [InlineData(GeneralNames.Initialize, 4)] public void Should_Contain_AllDefinedLanguageServerMethods(string key, int count) { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); handler.Add( Substitute.For(), Substitute.For(), @@ -90,7 +96,8 @@ public void Should_Contain_AllDefinedLanguageServerMethods(string key, int count [InlineData(GeneralNames.Initialize, 4)] public void Should_Contain_AllDefinedLanguageServerMethods_GivenDuplicates(string key, int count) { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); handler.Add( Substitute.For(), Substitute.For(), @@ -116,7 +123,8 @@ public void Should_Contain_AllDefinedLanguageServerMethods_GivenDuplicates(strin [InlineData(TextDocumentNames.DidSave, 8)] public void Should_Contain_AllDefinedMethods_ForDifferentKeys(string key, int count) { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); var sub = TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var sub2 = TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cake"), "csharp"); @@ -131,7 +139,8 @@ public void Should_Contain_AllDefinedMethods_ForDifferentKeys(string key, int co [InlineData(typeof(ILanguageProtocolInitializeHandler), typeof(ILanguageProtocolInitializedHandler), "initialize", "initialized", 2)] public void Should_Contain_AllDefinedMethods_OnLanguageServer(Type requestHandler, Type type2, string key, string key2, int count) { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); var sub = (IJsonRpcHandler) Substitute.For(new[] { requestHandler, type2 }, new object[0]); if (sub is IRegistration reg) reg.GetRegistrationOptions() @@ -150,7 +159,8 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer(Type requestHandle [InlineData(typeof(ILanguageProtocolInitializeHandler), typeof(ILanguageProtocolInitializedHandler), "initialize", "initialized", 2)] public void Should_Contain_AllDefinedMethods_OnLanguageServer_WithDifferentKeys(Type requestHandler, Type type2, string key, string key2, int count) { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); var sub = (IJsonRpcHandler) Substitute.For(new[] { requestHandler, type2 }, new object[0]); if (sub is IRegistration reg) reg.GetRegistrationOptions() @@ -178,7 +188,8 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer_WithDifferentKeys( [InlineData("somemethod", typeof(IJsonRpcRequestHandler, object>))] public void Should_AllowSpecificHandlers_ToBeAdded(string method, Type handlerType) { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); var sub = (IJsonRpcHandler) Substitute.For(new[] { handlerType }, new object[0]); var sub2 = (IJsonRpcHandler) Substitute.For(new[] { handlerType }, new object[0]); handler.Add(method, sub, null); @@ -192,7 +203,8 @@ public void Should_AllowSpecificHandlers_ToBeAdded(string method, Type handlerTy [MemberData(nameof(Should_DealWithClassesThatImplementMultipleHandlers_WithoutConflictingRegistrations_Data))] public void Should_DealWithClassesThatImplementMultipleHandlers_WithoutConflictingRegistrations(string method, IJsonRpcHandler sub) { - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); handler.Add(sub); var descriptor = handler.OfType().First(x => x.Method == method); @@ -210,7 +222,8 @@ public void Should_DealWithClassesThatImplementMultipleHandlers_BySettingKeyAcco } ); - var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()); + var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); handler.Add(codeLensHandler as IJsonRpcHandler); var descriptor = handler.OfType().Select(x => x.Key); diff --git a/test/Lsp.Tests/LspRequestRouterTests.cs b/test/Lsp.Tests/LspRequestRouterTests.cs index 8eb438b1b..ac5f65760 100644 --- a/test/Lsp.Tests/LspRequestRouterTests.cs +++ b/test/Lsp.Tests/LspRequestRouterTests.cs @@ -12,6 +12,7 @@ using NSubstitute; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.JsonRpc.Server; +using OmniSharp.Extensions.LanguageServer.Client; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; @@ -21,6 +22,7 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Server; using OmniSharp.Extensions.LanguageServer.Protocol.Server.WorkDone; using OmniSharp.Extensions.LanguageServer.Protocol.Shared; +using OmniSharp.Extensions.LanguageServer.Server; using OmniSharp.Extensions.LanguageServer.Server.Matchers; using OmniSharp.Extensions.LanguageServer.Shared; using Xunit; @@ -90,7 +92,15 @@ public async Task ShouldRouteToCorrect_Notification() .Returns(Unit.Value); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection( + SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider( + new[] { + typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, + typeof(LspRequestRouter).Assembly + } + ) + ) { textDocumentSyncHandler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -126,7 +136,15 @@ public async Task ShouldRouteToCorrect_Notification_WithManyHandlers() var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection( + SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider( + new[] { + typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, + typeof(LspRequestRouter).Assembly + } + ) + ) { textDocumentSyncHandler, textDocumentSyncHandler2 }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -165,7 +183,15 @@ public async Task ShouldRouteToCorrect_Request() .Returns(new CommandOrCodeActionContainer()); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection( + SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider( + new[] { + typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, + typeof(LspRequestRouter).Assembly + } + ) + ) { textDocumentSyncHandler, codeActionHandler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -217,7 +243,15 @@ public async Task ShouldRouteToCorrect_Request_WithManyHandlers() var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); var handlerCollection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection( + SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider( + new[] { + typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, + typeof(LspRequestRouter).Assembly + } + ) + ) { textDocumentSyncHandler, textDocumentSyncHandler2, codeActionHandler }; handlerCollection.Add(registry.Handlers); AutoSubstitute.Provide(handlerCollection); @@ -267,7 +301,15 @@ public async Task ShouldRouteToCorrect_Request_WithManyHandlers_CodeLensHandler( var tdi = new TextDocumentIdentifiers(); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, tdi, new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection( + SupportedCapabilitiesFixture.AlwaysTrue, tdi, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider( + new[] { + typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, + typeof(LspRequestRouter).Assembly + } + ) + ) { textDocumentSyncHandler, textDocumentSyncHandler2, codeActionHandler, codeActionHandler2 }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -299,7 +341,15 @@ public async Task ShouldRouteTo_CorrectRequestWhenGivenNullParams() .Returns(Unit.Value); var collection = - new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + new SharedHandlerCollection( + SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider( + new[] { + typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, + typeof(LspRequestRouter).Assembly + } + ) + ) { handler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); diff --git a/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs b/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs index fe6e6e447..825efae5c 100644 --- a/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs +++ b/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs @@ -4,10 +4,12 @@ using FluentAssertions; using Microsoft.Extensions.DependencyInjection; using NSubstitute; +using OmniSharp.Extensions.LanguageServer.Client; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Shared; +using OmniSharp.Extensions.LanguageServer.Server; using OmniSharp.Extensions.LanguageServer.Server.Matchers; using OmniSharp.Extensions.LanguageServer.Shared; using Xunit; @@ -58,7 +60,8 @@ public void Should_Return_Did_Open_Text_Document_Handler_Descriptor() TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); - var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider()) + var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -87,7 +90,8 @@ public void Should_Return_Did_Open_Text_Document_Handler_Descriptor_With_Sepcial TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cshtml"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); - var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider()) + var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -116,7 +120,8 @@ public void Should_Return_Did_Change_Text_Document_Descriptor() TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); - var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider()) + var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -143,7 +148,8 @@ public void Should_Return_Did_Save_Text_Document_Descriptor() TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); - var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider()) + var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -170,7 +176,8 @@ public void Should_Return_Did_Close_Text_Document_Descriptor() TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); - var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider()) + var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -197,7 +204,8 @@ public void Should_Return_Code_Lens_Descriptor() TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); - var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider()) + var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); @@ -255,7 +263,8 @@ public void Should_Return_Did_Folding_Range_handler() ); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); - var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider()) + var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler, handler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); diff --git a/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs b/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs index 806a98ebd..c839009a6 100644 --- a/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs +++ b/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs @@ -11,11 +11,14 @@ using NSubstitute; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.JsonRpc.Server; +using OmniSharp.Extensions.LanguageServer.Client; +using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Shared; +using OmniSharp.Extensions.LanguageServer.Server; using OmniSharp.Extensions.LanguageServer.Shared; using Xunit; using Xunit.Abstractions; @@ -46,7 +49,8 @@ public async Task RequestsCancellation() } ); - var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()) + var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider(), + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })) { textDocumentSyncHandler, codeActionHandler }; AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection);