public void Should_AllowUnsupportedCapabilities(IJsonRpcHandler handler, object instance)
        {
            var textDocumentSyncHandler =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp");

            var collection =
                new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider())
            {
                textDocumentSyncHandler, handler
            };
            var provider = new ClientCapabilityProvider(collection, true);

            HasHandler(provider, instance).Should().BeTrue();
        }
        public void Should_Contain_AllDefinedLanguageServerMethods(string key, int count)
        {
            var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For <IResolverContext>(),
                                                      new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly }));

            handler.Add(
                Substitute.For <ILanguageProtocolInitializeHandler>(),
                Substitute.For <ILanguageProtocolInitializedHandler>(),
                Substitute.For <IExitHandler>(),
                Substitute.For <IShutdownHandler>()
                );
            handler.Should().Contain(x => x.Method == key);
            handler.Should().HaveCount(count);
        }
        public async Task ShouldRouteToCorrect_Request()
        {
            var textDocumentSyncHandler =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp");

            textDocumentSyncHandler.Handle(Arg.Any <DidSaveTextDocumentParams>(), Arg.Any <CancellationToken>())
            .Returns(Unit.Value);

            var codeActionHandler = Substitute.For <ICodeActionHandler>();

            codeActionHandler.GetRegistrationOptions().Returns(new CodeActionRegistrationOptions {
                DocumentSelector = DocumentSelector.ForPattern("**/*.cs")
            });
            codeActionHandler
            .Handle(Arg.Any <CodeActionParams>(), Arg.Any <CancellationToken>())
            .Returns(new CommandOrCodeActionContainer());

            var collection =
                new SharedHandlerCollection(
                    SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For <IResolverContext>(),
                    new LspHandlerTypeDescriptorProvider(
                        new[] {
                typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly,
                typeof(LspRequestRouter).Assembly
            }
                        )
                    )
            {
                textDocumentSyncHandler, codeActionHandler
            };

            AutoSubstitute.Provide <IHandlerCollection>(collection);
            AutoSubstitute.Provide <IEnumerable <ILspHandlerDescriptor> >(collection);
            var mediator = AutoSubstitute.Resolve <LspRequestRouter>();

            var id      = Guid.NewGuid().ToString();
            var @params = new DidSaveTextDocumentParams {
                TextDocument = new TextDocumentIdentifier(new Uri("file:///c:/test/123.cs"))
            };

            var request = new Request(
                id, TextDocumentNames.CodeAction,
                JObject.Parse(JsonConvert.SerializeObject(@params, new Serializer(ClientVersion.Lsp3).Settings))
                );

            await mediator.RouteRequest(mediator.GetDescriptors(request), request, CancellationToken.None);

            await codeActionHandler.Received(1).Handle(Arg.Any <CodeActionParams>(), Arg.Any <CancellationToken>());
        }
Example #4
0
        public void Should_AllowNullSupportedCapabilities(IJsonRpcHandler handler, object instance)
        {
            var textDocumentSyncHandler =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp");

            var collection =
                new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For <IResolverContext>(),
                                            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);

            HasHandler(provider, instance).Should().BeTrue();
        }
        public void Should_Contain_AllConcreteDefinedMethods()
        {
            var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers());

            handler.Add(
                Substitute.For <IExitHandler>(),
                Substitute.For <ILanguageProtocolInitializeHandler>(),
                Substitute.For <ILanguageProtocolInitializedHandler>(),
                Substitute.For <IShutdownHandler>()
                );

            handler._handlers.Should().Contain(x => x.Method == "exit");
            handler._handlers.Should().Contain(x => x.Method == "shutdown");
            handler._handlers.Count.Should().Be(4);
        }
Example #6
0
        public void Should_Contain_AllDefinedMethods_ForDifferentKeys(string key, int count)
        {
            var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For <IResolverContext>(),
                                                      new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly }));

            handler.Initialize();
            var sub = TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp");

            var sub2 = TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cake"), "csharp");

            handler.Add(sub);
            handler.Add(sub2);
            handler.Should().Contain(x => x.Method == key);
            handler.Should().HaveCount(count);
        }
Example #7
0
        public void Should_AllowSpecificHandlers_ToBeAdded(string method, Type handlerType)
        {
            var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For <IResolverContext>(),
                                                      new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly }));

            handler.Initialize();

            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);
            handler.Add(method, sub2, null);
            handler.Should().Contain(x => x.Method == method);
            handler.Should().Contain(x => x.Method == method);
            handler.Should().HaveCount(1);
        }
        public ClientCapabilityProviderFixture()
        {
            var handler = Substitute.For <IExecuteCommandHandler>();

            handler.GetRegistrationOptions().Returns(new ExecuteCommandRegistrationOptions());

            var handlerCollection = new SharedHandlerCollection(
                SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider()
                )
            {
                handler
            };
            var capabilityProvider = new ClientCapabilityProvider(handlerCollection, true);

            Provider = capabilityProvider;
        }
        public void Should_Contain_AllDefinedMethods_OnLanguageServer(Type requestHandler, Type type2, string key, string key2, int count)
        {
            var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers());
            var sub     = (IJsonRpcHandler)Substitute.For(new Type[] { requestHandler, type2 }, new object[0]);

            if (sub is IRegistration <TextDocumentRegistrationOptions> reg)
            {
                reg.GetRegistrationOptions()
                .Returns(new TextDocumentRegistrationOptions()
                {
                    DocumentSelector = new DocumentSelector()
                });
            }
            handler.Add(sub);
            handler._handlers.Should().Contain(x => x.Method == key);
            handler._handlers.Should().Contain(x => x.Method == key2);
            handler._handlers.Count.Should().Be(count);
        }
        public void Should_DealWithClassesThatImplementMultipleHandlers_BySettingKeyAccordingly()
        {
            var codeLensHandler = Substitute.For(new Type[] { typeof(ICodeLensHandler), typeof(ICodeLensResolveHandler) }, new object[0]);

            ((ICodeLensHandler)codeLensHandler).GetRegistrationOptions()
            .Returns(new CodeLensRegistrationOptions()
            {
                DocumentSelector = new DocumentSelector(DocumentFilter.ForLanguage("foo"))
            });

            var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers());

            handler.Add(codeLensHandler as IJsonRpcHandler);

            var descriptor = handler._handlers.Select(x => x.Key);

            descriptor.Should().BeEquivalentTo(new [] { "[foo]", "[foo]" });
        }
Example #11
0
        public void Should_Return_Did_Folding_Range_handler()
        {
            // Given
            var textDocumentSyncHandler =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.ps*1"), "powershell");
            var handler = Substitute.For <IFoldingRangeHandler>();

            handler.GetRegistrationOptions().Returns(
                new FoldingRangeRegistrationOptions {
                DocumentSelector = new DocumentSelector(new DocumentFilter {
                    Pattern = "**/*.ps*1"
                })
            }
                );
            var textDocumentIdentifiers = new TextDocumentIdentifiers();

            AutoSubstitute.Provide(textDocumentIdentifiers);
            var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, Substitute.For <IResolverContext>(),
                                                         new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly }))
            {
                textDocumentSyncHandler, handler
            };

            AutoSubstitute.Provide <IHandlerCollection>(collection);
            AutoSubstitute.Provide <IEnumerable <ILspHandlerDescriptor> >(collection);
            var handlerMatcher = AutoSubstitute.Resolve <TextDocumentMatcher>();

            // When
            var result = handlerMatcher.FindHandler(
                new FoldingRangeRequestParam {
                TextDocument = new TextDocumentItem {
                    Uri = new Uri("file:///abc/123/d.ps1")
                }
            },
                collection.Where(x => x.Method == TextDocumentNames.DidOpen)
                );

            // Then
            var lspHandlerDescriptors = result as ILspHandlerDescriptor[] ?? result.ToArray();

            lspHandlerDescriptors.Should().NotBeNullOrEmpty();
            lspHandlerDescriptors.Should().Contain(x => x.Method == TextDocumentNames.DidOpen);
        }
Example #12
0
        public ClientCapabilityProviderFixture()
        {
            var handler = Substitute.For <IExecuteCommandHandler>();

            handler.GetRegistrationOptions().Returns(new ExecuteCommandRegistrationOptions());

            var handlerCollection = new SharedHandlerCollection(
                SupportedCapabilitiesFixture.AlwaysTrue,
                new TextDocumentIdentifiers(),
                Substitute.For <IResolverContext>(),
                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);

            Provider = capabilityProvider;
        }
        public async Task ShouldRouteToCorrect_Notification_WithManyHandlers()
        {
            var textDocumentSyncHandler =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp");
            var textDocumentSyncHandler2 =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cake"), "csharp");

            textDocumentSyncHandler.Handle(Arg.Any <DidSaveTextDocumentParams>(), Arg.Any <CancellationToken>())
            .Returns(Unit.Value);
            textDocumentSyncHandler2.Handle(Arg.Any <DidSaveTextDocumentParams>(), Arg.Any <CancellationToken>())
            .Returns(Unit.Value);

            var textDocumentIdentifiers = new TextDocumentIdentifiers();

            AutoSubstitute.Provide(textDocumentIdentifiers);
            var collection =
                new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider())
            {
                textDocumentSyncHandler, textDocumentSyncHandler2
            };

            AutoSubstitute.Provide <IHandlerCollection>(collection);
            AutoSubstitute.Provide <IEnumerable <ILspHandlerDescriptor> >(collection);
            AutoSubstitute.Provide <IHandlerMatcher>(new TextDocumentMatcher(LoggerFactory.CreateLogger <TextDocumentMatcher>(), textDocumentIdentifiers));
            var mediator = AutoSubstitute.Resolve <LspRequestRouter>();

            var @params = new DidSaveTextDocumentParams {
                TextDocument = new TextDocumentIdentifier(new Uri("file:///c:/test/123.cake"))
            };

            var request = new Notification(
                TextDocumentNames.DidSave,
                JObject.Parse(JsonConvert.SerializeObject(@params, new Serializer(ClientVersion.Lsp3).Settings))
                );

            await mediator.RouteNotification(mediator.GetDescriptors(request), request, CancellationToken.None);

            await textDocumentSyncHandler.Received(0)
            .Handle(Arg.Any <DidSaveTextDocumentParams>(), Arg.Any <CancellationToken>());

            await textDocumentSyncHandler2.Received(1)
            .Handle(Arg.Any <DidSaveTextDocumentParams>(), Arg.Any <CancellationToken>());
        }
        public void Should_Contain_AllDefinedMethods_OnLanguageServer(Type requestHandler, Type type2, string key, string key2, int count)
        {
            var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For <IResolverContext>(),
                                                      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 <TextDocumentRegistrationOptions> reg)
            {
                reg.GetRegistrationOptions()
                .Returns(
                    new TextDocumentRegistrationOptions {
                    DocumentSelector = new DocumentSelector()
                }
                    );
            }
            handler.Add(sub);
            handler.Should().Contain(x => x.Method == key);
            handler.Should().Contain(x => x.Method == key2);
            handler.Should().HaveCount(count);
        }
        public void Should_DealWithClassesThatImplementMultipleHandlers_BySettingKeyAccordingly()
        {
            var codeLensHandler = Substitute.For(new[] { typeof(ICodeLensHandler), typeof(ICodeLensResolveHandler) }, new object[0]);

            ((ICodeLensHandler)codeLensHandler).GetRegistrationOptions()
            .Returns(
                new CodeLensRegistrationOptions {
                DocumentSelector = new DocumentSelector(DocumentFilter.ForLanguage("foo"))
            }
                );

            var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For <IResolverContext>(),
                                                      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 <LspHandlerDescriptor>().Select(x => x.Key);

            descriptor.Should().BeEquivalentTo("[foo]", "[foo]");
        }
        public void Should_Contain_AllDefinedLanguageServerMethods_GivenDuplicates(string key, int count)
        {
            var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers());

            handler.Add(
                Substitute.For <ILanguageProtocolInitializeHandler>(),
                Substitute.For <ILanguageProtocolInitializedHandler>(),
                Substitute.For <IExitHandler>(),
                Substitute.For <IShutdownHandler>(),
                Substitute.For <ILanguageProtocolInitializeHandler>(),
                Substitute.For <ILanguageProtocolInitializedHandler>(),
                Substitute.For <IExitHandler>(),
                Substitute.For <IShutdownHandler>(),
                Substitute.For <ILanguageProtocolInitializeHandler>(),
                Substitute.For <ILanguageProtocolInitializedHandler>(),
                Substitute.For <IExitHandler>(),
                Substitute.For <IShutdownHandler>()
                );
            handler._handlers.Should().Contain(x => x.Method == key);
            handler._handlers.Count.Should().Be(count);
        }
Example #17
0
        public void Should_Return_Did_Folding_Range_handler()
        {
            // Given
            var textDocumentSyncHandler =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.ps*1"), "powershell");
            var handler = Substitute.For <IFoldingRangeHandler>();

            handler.GetRegistrationOptions().Returns(
                new FoldingRangeRegistrationOptions {
                DocumentSelector = new DocumentSelector(new DocumentFilter {
                    Pattern = "**/*.ps*1"
                })
            }
                );
            var textDocumentIdentifiers = new TextDocumentIdentifiers();

            AutoSubstitute.Provide(textDocumentIdentifiers);
            var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider())
            {
                textDocumentSyncHandler, handler
            };

            AutoSubstitute.Provide <IHandlerCollection>(collection);
            AutoSubstitute.Provide <IEnumerable <ILspHandlerDescriptor> >(collection);
            var handlerMatcher = AutoSubstitute.Resolve <TextDocumentMatcher>();

            // When
            var result = handlerMatcher.FindHandler(
                new FoldingRangeRequestParam {
                TextDocument = new TextDocumentItem {
                    Uri = new Uri("file:///abc/123/d.ps1")
                }
            },
                collection.Where(x => x.Method == TextDocumentNames.DidOpen)
                );

            // Then
            result.Should().NotBeNullOrEmpty();
            result.Should().Contain(x => x.Method == TextDocumentNames.DidOpen);
        }
        public void GH162_TextDocumentSync_Should_Work_Without_WillSave_Or_WillSaveWaitUntil()
        {
            var textDocumentSyncHandler =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp");

            var collection =
                new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), new ServiceCollection().BuildServiceProvider())
            {
                textDocumentSyncHandler
            };
            var provider     = new ClientCapabilityProvider(collection, true);
            var capabilities = new ClientCapabilities {
                TextDocument = new TextDocumentClientCapabilities {
                    Synchronization = new SynchronizationCapability {
                        DidSave             = true,
                        DynamicRegistration = false,
                        WillSave            = true,
                        WillSaveWaitUntil   = true
                    },
                }
            };

            provider.HasStaticHandler(capabilities.TextDocument.Synchronization).Should().BeTrue();
        }
Example #19
0
        public void Should_Handle_Mixed_Capabilities()
        {
            var textDocumentSyncHandler =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp");

            var codeActionHandler     = Substitute.For <ICodeActionHandler>();
            var definitionHandler     = Substitute.For <IDefinitionHandler>();
            var typeDefinitionHandler = Substitute.For <ITypeDefinitionHandler>();

            var collection =
                new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For <IResolverContext>(),
                                            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 {
                TextDocument = new TextDocumentClientCapabilities {
                    CodeAction = new Supports <CodeActionCapability?>(
                        true, new CodeActionCapability {
                        DynamicRegistration = false,
                    }
                        ),
                    TypeDefinition = new Supports <TypeDefinitionCapability?>(
                        true, new TypeDefinitionCapability {
                        DynamicRegistration = true,
                    }
                        )
                }
            };

//            provider.GetStaticOptions(capabilities.TextDocument.CodeAction)
//                    .Get<ICodeActionOptions, CodeActionRegistrationOptions.StaticOptions>(CodeActionRegistrationOptions.StaticOptions.Of).Should().NotBeNull();
            provider.HasStaticHandler(capabilities.TextDocument.Definition).Should().BeTrue();
            provider.HasStaticHandler(capabilities.TextDocument.TypeDefinition).Should().BeFalse();
        }
        internal LanguageClient(LanguageClientOptions options) : base(options)
        {
            _capabilities       = options.SupportedCapabilities;
            _clientCapabilities = options.ClientCapabilities;
            var services = options.Services;

            services.AddLogging(builder => options.LoggingBuilderAction(builder));
            options.RequestProcessIdentifier ??= (options.SupportsContentModified
                ? new RequestProcessIdentifier(RequestProcessType.Parallel)
                : new RequestProcessIdentifier(RequestProcessType.Serial));
            // services.AddSingleton<IOptionsMonitor<LoggerFilterOptions>, LanguageClientLoggerFilterOptions>();

            _clientInfo = options.ClientInfo;
            _receiver   = options.Receiver;
            var serializer            = options.Serializer;
            var supportedCapabilities = new SupportedCapabilities();

            _textDocumentIdentifiers = new TextDocumentIdentifiers();
            var collection = new SharedHandlerCollection(supportedCapabilities, _textDocumentIdentifiers);

            services.AddSingleton <IHandlersManager>(collection);
            _collection = collection;
            // _initializeDelegates = initializeDelegates;
            // _initializedDelegates = initializedDelegates;
            _startedDelegates      = options.StartedDelegates;
            _rootUri               = options.RootUri;
            _trace                 = options.Trace;
            _initializationOptions = options.InitializationOptions;

            services.AddSingleton <IOutputHandler>(_ =>
                                                   new OutputHandler(options.Output, options.Serializer, options.Receiver.ShouldFilterOutput, _.GetService <ILogger <OutputHandler> >()));
            services.AddSingleton(_collection);
            services.AddSingleton(_textDocumentIdentifiers);
            services.AddSingleton(serializer);
            services.AddSingleton <OmniSharp.Extensions.JsonRpc.ISerializer>(serializer);
            services.AddSingleton(options.RequestProcessIdentifier);
            services.AddSingleton <OmniSharp.Extensions.JsonRpc.IReceiver>(options.Receiver);
            services.AddSingleton(options.Receiver);
            services.AddSingleton <ILanguageClient>(this);
            services.AddSingleton <LspRequestRouter>();
            services.AddSingleton <IRequestRouter <ILspHandlerDescriptor> >(_ => _.GetRequiredService <LspRequestRouter>());
            services.AddSingleton <IRequestRouter <IHandlerDescriptor> >(_ => _.GetRequiredService <LspRequestRouter>());
            services.AddSingleton <IResponseRouter, ResponseRouter>();

            services.AddSingleton <IProgressManager, ProgressManager>();
            services.AddSingleton(_ => _.GetRequiredService <IProgressManager>() as IJsonRpcHandler);
            services.AddSingleton <IClientWorkDoneManager, ClientWorkDoneManager>();
            services.AddSingleton(_ => _.GetRequiredService <IClientWorkDoneManager>() as IJsonRpcHandler);

            EnsureAllHandlersAreRegistered();

            services.AddSingleton <RegistrationManager>();
            services.AddSingleton <IRegistrationManager>(_ => _.GetRequiredService <RegistrationManager>());
            if (options.DynamicRegistration)
            {
                services.AddSingleton(_ => _.GetRequiredService <RegistrationManager>() as IJsonRpcHandler);
            }

            var workspaceFoldersManager = new WorkspaceFoldersManager(this);

            services.AddSingleton(workspaceFoldersManager);
            services.AddSingleton <IWorkspaceFoldersManager>(workspaceFoldersManager);
            if (options.WorkspaceFolders)
            {
                services.AddSingleton <IJsonRpcHandler>(workspaceFoldersManager);
            }

            var serviceProvider = services.BuildServiceProvider();

            _disposable.Add(serviceProvider);
            _serviceProvider = serviceProvider;
            collection.SetServiceProvider(_serviceProvider);

            _responseRouter          = _serviceProvider.GetRequiredService <IResponseRouter>();
            _progressManager         = _serviceProvider.GetRequiredService <IProgressManager>();
            _workDoneManager         = _serviceProvider.GetRequiredService <IClientWorkDoneManager>();
            _registrationManager     = _serviceProvider.GetRequiredService <RegistrationManager>();
            _workspaceFoldersManager = _serviceProvider.GetRequiredService <IWorkspaceFoldersManager>();

            _connection = new Connection(
                options.Input,
                _serviceProvider.GetRequiredService <IOutputHandler>(),
                options.Receiver,
                options.RequestProcessIdentifier,
                _serviceProvider.GetRequiredService <IRequestRouter <IHandlerDescriptor> >(),
                _responseRouter,
                _serviceProvider.GetRequiredService <ILoggerFactory>(),
                options.OnUnhandledException ?? (e => { }),
                options.CreateResponseException,
                options.MaximumRequestTimeout,
                options.SupportsContentModified,
                options.Concurrency
                );

            // We need to at least create Window here in case any handler does loggin in their constructor
            TextDocument = new TextDocumentLanguageClient(this, _serviceProvider);
            Client       = new ClientLanguageClient(this, _serviceProvider);
            General      = new GeneralLanguageClient(this, _serviceProvider);
            Window       = new WindowLanguageClient(this, _serviceProvider);
            Workspace    = new WorkspaceLanguageClient(this, _serviceProvider);

            workspaceFoldersManager.Add(options.Folders);

            var serviceHandlers    = _serviceProvider.GetServices <IJsonRpcHandler>().ToArray();
            var serviceIdentifiers = _serviceProvider.GetServices <ITextDocumentIdentifier>().ToArray();

            _disposable.Add(_textDocumentIdentifiers.Add(serviceIdentifiers));
            _disposable.Add(_collection.Add(serviceHandlers));
            options.AddLinks(_collection);
        }
        internal LanguageServer(LanguageServerOptions options) : base(options)
        {
            var services = options.Services;
            var configurationProvider = new DidChangeConfigurationProvider(this, options.ConfigurationBuilderAction);

            services.AddSingleton <IJsonRpcHandler>(configurationProvider);
            options.RequestProcessIdentifier ??= (options.SupportsContentModified
                ? new RequestProcessIdentifier(RequestProcessType.Parallel)
                : new RequestProcessIdentifier(RequestProcessType.Serial));

            services.AddSingleton <IConfiguration>(configurationProvider);
            services.AddSingleton(Configuration = configurationProvider);

            services.AddLogging(builder => options.LoggingBuilderAction(builder));
            services.AddSingleton <IOptionsMonitor <LoggerFilterOptions>, LanguageServerLoggerFilterOptions>();

            _serverInfo              = options.ServerInfo;
            _serverReceiver          = options.Receiver;
            _serializer              = options.Serializer;
            _supportedCapabilities   = new SupportedCapabilities();
            _textDocumentIdentifiers = new TextDocumentIdentifiers();
            var collection = new SharedHandlerCollection(_supportedCapabilities, _textDocumentIdentifiers);

            services.AddSingleton <IHandlersManager>(collection);
            _collection           = collection;
            _initializeDelegates  = options.InitializeDelegates;
            _initializedDelegates = options.InitializedDelegates;
            _startedDelegates     = options.StartedDelegates;

            services.AddSingleton <IOutputHandler>(_ => new OutputHandler(
                                                       options.Output,
                                                       options.Serializer,
                                                       options.Receiver.ShouldFilterOutput,
                                                       _.GetService <ILogger <OutputHandler> >())
                                                   );
            services.AddSingleton(_collection);
            services.AddSingleton(_textDocumentIdentifiers);
            services.AddSingleton(_serializer);
            services.AddSingleton <OmniSharp.Extensions.JsonRpc.ISerializer>(_serializer);
            services.AddSingleton(options.RequestProcessIdentifier);
            services.AddSingleton <OmniSharp.Extensions.JsonRpc.IReceiver>(options.Receiver);
            services.AddSingleton <ILspServerReceiver>(options.Receiver);

            services.AddTransient <IHandlerMatcher, TextDocumentMatcher>();
            services.AddSingleton <ILanguageServer>(this);
            services.AddTransient <IHandlerMatcher, ExecuteCommandMatcher>();
            services.AddTransient <IHandlerMatcher, ResolveCommandMatcher>();
            services.AddSingleton <LspRequestRouter>();
            services.AddSingleton <IRequestRouter <ILspHandlerDescriptor> >(_ => _.GetRequiredService <LspRequestRouter>());
            services.AddSingleton <IRequestRouter <IHandlerDescriptor> >(_ => _.GetRequiredService <LspRequestRouter>());
            services.AddSingleton <IResponseRouter, ResponseRouter>();
            services.AddTransient(typeof(IPipelineBehavior <,>), typeof(ResolveCommandPipeline <,>));

            services.AddSingleton <IProgressManager, ProgressManager>();
            services.AddSingleton <IJsonRpcHandler>(_ => _.GetRequiredService <IProgressManager>() as IJsonRpcHandler);
            services.AddSingleton <IServerWorkDoneManager, ServerWorkDoneManager>();
            services.AddSingleton <IJsonRpcHandler>(_ => _.GetRequiredService <IServerWorkDoneManager>() as IJsonRpcHandler);

            EnsureAllHandlersAreRegistered();

            var serviceProvider = services.BuildServiceProvider();

            _disposable.Add(serviceProvider);
            _serviceProvider = serviceProvider;
            collection.SetServiceProvider(_serviceProvider);

            var requestRouter = _serviceProvider.GetRequiredService <IRequestRouter <ILspHandlerDescriptor> >();

            _responseRouter        = _serviceProvider.GetRequiredService <IResponseRouter>();
            ProgressManager        = _serviceProvider.GetRequiredService <IProgressManager>();
            _serverWorkDoneManager = _serviceProvider.GetRequiredService <IServerWorkDoneManager>();
            _connection            = new Connection(
                options.Input,
                _serviceProvider.GetRequiredService <IOutputHandler>(),
                options.Receiver,
                options.RequestProcessIdentifier,
                _serviceProvider.GetRequiredService <IRequestRouter <IHandlerDescriptor> >(),
                _responseRouter,
                _serviceProvider.GetRequiredService <ILoggerFactory>(),
                options.OnUnhandledException ?? (e => { ForcefulShutdown(); }),
                options.CreateResponseException,
                options.MaximumRequestTimeout,
                options.SupportsContentModified,
                options.Concurrency
                );

            // We need to at least create Window here in case any handler does loggin in their constructor
            TextDocument = new TextDocumentLanguageServer(this, _serviceProvider);
            Client       = new ClientLanguageServer(this, _serviceProvider);
            General      = new GeneralLanguageServer(this, _serviceProvider);
            Window       = new WindowLanguageServer(this, _serviceProvider);
            Workspace    = new WorkspaceLanguageServer(this, _serviceProvider);

            _disposable.Add(_collection.Add(this));

            {
                var serviceHandlers    = _serviceProvider.GetServices <IJsonRpcHandler>().ToArray();
                var serviceIdentifiers = _serviceProvider.GetServices <ITextDocumentIdentifier>().ToArray();
                _disposable.Add(_textDocumentIdentifiers.Add(serviceIdentifiers));
                _disposable.Add(_collection.Add(serviceHandlers));
                options.AddLinks(_collection);
            }
        }
        internal LanguageServer(
            Connection connection,
            IResponseRouter responseRouter,
            IOptions <LanguageServerOptions> options,
            ILanguageServerConfiguration configuration,
            ServerInfo serverInfo,
            ILspServerReceiver receiver,
            ISerializer serializer,
            IResolverContext resolverContext,
            ISupportedCapabilities supportedCapabilities,
            TextDocumentIdentifiers textDocumentIdentifiers,
            IEnumerable <OnLanguageServerInitializeDelegate> initializeDelegates,
            IEnumerable <OnLanguageServerInitializedDelegate> initializedDelegates,
            IEnumerable <OnLanguageServerStartedDelegate> startedDelegates,
            IEnumerable <IOnLanguageServerStarted> startedHandlers,
            IServerWorkDoneManager serverWorkDoneManager,
            ITextDocumentLanguageServer textDocumentLanguageServer,
            IClientLanguageServer clientLanguageServer,
            IGeneralLanguageServer generalLanguageServer,
            IWindowLanguageServer windowLanguageServer,
            IWorkspaceLanguageServer workspaceLanguageServer,
            LanguageProtocolSettingsBag languageProtocolSettingsBag,
            SharedHandlerCollection handlerCollection,
            IProgressManager progressManager,
            ILanguageServerWorkspaceFolderManager workspaceFolderManager, IEnumerable <IOnLanguageServerInitialize> initializeHandlers,
            IEnumerable <IOnLanguageServerInitialized> initializedHandlers,
            IEnumerable <IRegistrationOptionsConverter> registrationOptionsConverters,
            InstanceHasStarted instanceHasStarted
            ) : base(handlerCollection, responseRouter)
        {
            Configuration = configuration;

            _connection              = connection;
            _serverInfo              = serverInfo;
            _serverReceiver          = receiver;
            _serializer              = serializer;
            _supportedCapabilities   = supportedCapabilities;
            _textDocumentIdentifiers = textDocumentIdentifiers;
            _initializeDelegates     = initializeDelegates;
            _initializedDelegates    = initializedDelegates;
            _startedDelegates        = startedDelegates;
            _startedHandlers         = startedHandlers;
            WorkDoneManager          = serverWorkDoneManager;
            _settingsBag             = languageProtocolSettingsBag;
            Services    = _resolverContext = resolverContext;
            _collection = handlerCollection;

            // We need to at least create Window here in case any handler does logging in their constructor
            TextDocument                   = textDocumentLanguageServer;
            Client                         = clientLanguageServer;
            General                        = generalLanguageServer;
            Window                         = windowLanguageServer;
            Workspace                      = workspaceLanguageServer;
            ProgressManager                = progressManager;
            WorkspaceFolderManager         = workspaceFolderManager;
            _initializeHandlers            = initializeHandlers;
            _initializedHandlers           = initializedHandlers;
            _registrationOptionsConverters = registrationOptionsConverters;
            _instanceHasStarted            = instanceHasStarted;
            _concurrency                   = options.Value.Concurrency;

            _capabilityTypes = options
                               .Value.Assemblies
                               .SelectMany(z => z.ExportedTypes)
                               .Where(z => z.IsClass && !z.IsAbstract)
                               .Where(z => typeof(ICapability).IsAssignableFrom(z))
                               .Where(z => z.GetCustomAttributes <CapabilityKeyAttribute>().Any())
                               .ToLookup(z => string.Join(".", z.GetCustomAttribute <CapabilityKeyAttribute>().Keys));

            _disposable.Add(_collection.Add(this));
        }
        public async Task ShouldRouteToCorrect_Request_WithManyHandlers()
        {
            var textDocumentSyncHandler =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp");
            var textDocumentSyncHandler2 =
                TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cake"), "csharp");

            textDocumentSyncHandler.Handle(Arg.Any <DidSaveTextDocumentParams>(), Arg.Any <CancellationToken>())
            .Returns(Unit.Value);
            textDocumentSyncHandler2.Handle(Arg.Any <DidSaveTextDocumentParams>(), Arg.Any <CancellationToken>())
            .Returns(Unit.Value);

            var codeActionHandler = Substitute.For <ICodeActionHandler>();

            codeActionHandler.GetRegistrationOptions().Returns(new CodeActionRegistrationOptions {
                DocumentSelector = DocumentSelector.ForPattern("**/*.cs")
            });
            codeActionHandler
            .Handle(Arg.Any <CodeActionParams>(), Arg.Any <CancellationToken>())
            .Returns(new CommandOrCodeActionContainer());

            var registry           = new TestLanguageServerRegistry();
            var codeActionDelegate =
                Substitute.For <Func <CodeActionParams, CancellationToken, Task <CommandOrCodeActionContainer> > >();

            codeActionDelegate.Invoke(Arg.Any <CodeActionParams>(), Arg.Any <CancellationToken>())
            .Returns(new CommandOrCodeActionContainer());
            registry.OnCodeAction(
                codeActionDelegate,
                new CodeActionRegistrationOptions {
                DocumentSelector = DocumentSelector.ForPattern("**/*.cake")
            }
                );

            var textDocumentIdentifiers = new TextDocumentIdentifiers();

            AutoSubstitute.Provide(textDocumentIdentifiers);
            var handlerCollection =
                new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, new ServiceCollection().BuildServiceProvider())
            {
                textDocumentSyncHandler, textDocumentSyncHandler2, codeActionHandler
            };

            handlerCollection.Add(registry.Handlers);
            AutoSubstitute.Provide <IHandlerCollection>(handlerCollection);
            AutoSubstitute.Provide <IEnumerable <ILspHandlerDescriptor> >(handlerCollection);
            AutoSubstitute.Provide <IHandlerMatcher>(new TextDocumentMatcher(LoggerFactory.CreateLogger <TextDocumentMatcher>(), textDocumentIdentifiers));
            var mediator = AutoSubstitute.Resolve <LspRequestRouter>();

            var id      = Guid.NewGuid().ToString();
            var @params = new CodeActionParams {
                TextDocument = new TextDocumentIdentifier(new Uri("file:///c:/test/123.cake"))
            };

            var request = new Request(
                id, TextDocumentNames.CodeAction,
                JObject.Parse(JsonConvert.SerializeObject(@params, new Serializer(ClientVersion.Lsp3).Settings))
                );

            await mediator.RouteRequest(mediator.GetDescriptors(request), request, CancellationToken.None);

            await codeActionHandler.Received(0).Handle(Arg.Any <CodeActionParams>(), Arg.Any <CancellationToken>());

            await codeActionDelegate.Received(1).Invoke(Arg.Any <CodeActionParams>(), Arg.Any <CancellationToken>());
        }
        internal LanguageClient(
            Connection connection,
            IOptions <LanguageClientOptions> options,
            IEnumerable <ICapability> capabilities,
            ClientInfo clientInfo,
            ClientCapabilities clientCapabilities,
            ILspClientReceiver lspClientReceiver,
            TextDocumentIdentifiers textDocumentIdentifiers,
            IResolverContext resolverContext,
            IEnumerable <OnLanguageClientStartedDelegate> startedDelegates,
            IEnumerable <IOnLanguageClientStarted> startedHandlers,
            ITextDocumentLanguageClient textDocumentLanguageClient,
            IClientLanguageClient clientLanguageClient,
            IGeneralLanguageClient generalLanguageClient,
            IWindowLanguageClient windowLanguageClient,
            IWorkspaceLanguageClient workspaceLanguageClient,
            LanguageProtocolSettingsBag languageProtocolSettingsBag,
            SharedHandlerCollection handlerCollection,
            IResponseRouter responseRouter,
            IProgressManager progressManager,
            IClientWorkDoneManager clientWorkDoneManager,
            IRegistrationManager registrationManager,
            ILanguageClientWorkspaceFoldersManager languageClientWorkspaceFoldersManager, IEnumerable <OnLanguageClientInitializeDelegate> initializeDelegates,
            IEnumerable <IOnLanguageClientInitialize> initializeHandlers, IEnumerable <OnLanguageClientInitializedDelegate> initializedDelegates,
            IEnumerable <IOnLanguageClientInitialized> initializedHandlers,
            ISerializer serializer,
            InstanceHasStarted instanceHasStarted
            ) : base(handlerCollection, responseRouter)
        {
            _connection              = connection;
            _capabilities            = capabilities;
            _clientCapabilities      = clientCapabilities;
            _clientInfo              = clientInfo;
            _receiver                = lspClientReceiver;
            _textDocumentIdentifiers = textDocumentIdentifiers;
            _startedDelegates        = startedDelegates;
            _startedHandlers         = startedHandlers;
            _rootUri = options.Value.RootUri;
            _trace   = options.Value.Trace;
            _initializationOptions = options.Value.InitializationOptions;
            _settingsBag           = languageProtocolSettingsBag;
            _collection            = handlerCollection;
            Services = _resolverContext = resolverContext;

            _responseRouter         = responseRouter;
            ProgressManager         = progressManager;
            WorkDoneManager         = clientWorkDoneManager;
            RegistrationManager     = registrationManager;
            WorkspaceFoldersManager = languageClientWorkspaceFoldersManager;
            _initializeDelegates    = initializeDelegates;
            _initializeHandlers     = initializeHandlers;
            _initializedDelegates   = initializedDelegates;
            _initializedHandlers    = initializedHandlers;
            _serializer             = serializer;
            _instanceHasStarted     = instanceHasStarted;
            _concurrency            = options.Value.Concurrency;

            // We need to at least create Window here in case any handler does loggin in their constructor
            TextDocument = textDocumentLanguageClient;
            Client       = clientLanguageClient;
            General      = generalLanguageClient;
            Window       = windowLanguageClient;
            Workspace    = workspaceLanguageClient;
        }