public async Task Should_Update_CodeLensContainer_With_HandlerType()
        {
            // Given
            var resolveHandler = Substitute.For(new Type[] {
                typeof(ICodeLensHandler),
                typeof(ICodeLensResolveHandler)
            }, new object[0]);

            (resolveHandler as ICodeLensResolveHandler).CanResolve(Arg.Any <CodeLens>()).Returns(true);
            var descriptor = new LspHandlerDescriptor(
                TextDocumentNames.CodeLens,
                "Key",
                resolveHandler as IJsonRpcHandler,
                resolveHandler.GetType(),
                typeof(CodeLensParams),
                null,
                null,
                () => false,
                null,
                null,
                () => { },
                Substitute.For <ILspHandlerTypeDescriptor>());
            var handlerMatcher = new ResolveCommandPipeline <CodeLensParams, CodeLensContainer>(
                new RequestContext()
            {
                Descriptor = descriptor
            },
                Substitute.For <ILogger <ResolveCommandPipeline <CodeLensParams, CodeLensContainer> > >());

            var item = new CodeLens()
            {
                Data = JObject.FromObject(new { hello = "world" })
            };
            var list = new CodeLensContainer(new[] { item });

            (list is IEnumerable <ICanBeResolved>).Should().BeTrue();

            // When
            var response = await handlerMatcher.Handle(new CodeLensParams(), CancellationToken.None, () => Task.FromResult(list));

            // Then
            response.Should().BeEquivalentTo(list);
            (response as CodeLensContainer).Should().Contain(item);
            var responseItem = (response as CodeLensContainer).First();

            responseItem.Data[ResolveCommandMatcher.PrivateHandlerTypeName].Value <string>().Should().NotBeNullOrEmpty();
            responseItem.Data[ResolveCommandMatcher.PrivateHandlerKey].Value <string>().Should().NotBeNullOrEmpty();
            responseItem.Data["data"]["hello"].Value <string>().Should().Be("world");
        }
        public async Task Should_Update_CodeLens_Removing_HandlerType()
        {
            // Given
            var resolveHandler = Substitute.For(
                new[] {
                typeof(ICodeLensHandler),
                typeof(ICodeLensResolveHandler),
                typeof(ICanBeIdentifiedHandler)
            }, new object[0]
                );

            (resolveHandler as ICanBeIdentifiedHandler)?.Id.Returns(TrueId);
            var descriptor = new LspHandlerDescriptor(
                TextDocumentNames.CodeLensResolve,
                "Key",
                resolveHandler as IJsonRpcHandler,
                resolveHandler.GetType(),
                typeof(CodeLens),
                null,
                null,
                () => false,
                null,
                null,
                () => { },
                Substitute.For <ILspHandlerTypeDescriptor>()
                );
            var handlerMatcher = new ResolveCommandPipeline <CodeLens, CodeLens>(
                new RequestContext {
                Descriptor = descriptor
            },
                Substitute.For <ILogger <ResolveCommandPipeline <CodeLens, CodeLens> > >()
                );

            var item = new CodeLens {
                Data = JObject.FromObject(new { hello = "world" })
            };

            item.Data[Constants.PrivateHandlerId] = Guid.Empty;

            // When
            var response = await handlerMatcher.Handle(item, CancellationToken.None, () => Task.FromResult(item));

            // Then
            response.Should().BeEquivalentTo(item);
            item.Data?[Constants.PrivateHandlerId].Value <Guid>().Should().BeEmpty();
            item.Data["hello"].Value <string>().Should().Be("world");
        }
        public async Task Should_Update_CodeLens_Removing_HandlerType()
        {
            // Given
            var resolveHandler = Substitute.For(new Type[] {
                typeof(ICodeLensHandler),
                typeof(ICodeLensResolveHandler)
            }, new object[0]);

            (resolveHandler as ICodeLensResolveHandler).CanResolve(Arg.Any <CodeLens>()).Returns(true);
            var descriptor = new LspHandlerDescriptor(
                TextDocumentNames.CodeLensResolve,
                "Key",
                resolveHandler as IJsonRpcHandler,
                resolveHandler.GetType(),
                typeof(CodeLens),
                null,
                null,
                () => false,
                null,
                null,
                () => { },
                Substitute.For <ILspHandlerTypeDescriptor>());
            var handlerMatcher = new ResolveCommandPipeline <CodeLens, CodeLens>(
                new RequestContext()
            {
                Descriptor = descriptor
            },
                Substitute.For <ILogger <ResolveCommandPipeline <CodeLens, CodeLens> > >());

            var item = new CodeLens()
            {
                Data = JObject.FromObject(new { data = new { hello = "world" } })
            };

            item.Data[ResolveCommandMatcher.PrivateHandlerTypeName] = resolveHandler.GetType().FullName;

            // When
            var response = await handlerMatcher.Handle(item, CancellationToken.None, () => Task.FromResult(item));

            // Then
            response.Should().BeEquivalentTo(item);
            item.Data?[ResolveCommandMatcher.PrivateHandlerTypeName].Should().BeNull();
            item.Data["hello"].Value <string>().Should().Be("world");
        }
        IDisposable IHandlersManager.AddLink(string fromMethod, string toMethod)
        {
            var source = _descriptors.FirstOrDefault(z => z.Method == fromMethod);

            if (source == null)
            {
                if (_descriptors.Any(z => z.Method == toMethod))
                {
                    throw new ArgumentException(
                              $"Could not find descriptor for '{fromMethod}', but I did find one for '{toMethod}'.  Did you mean to link '{toMethod}' to '{fromMethod}' instead?", fromMethod
                              );
                }

                throw new ArgumentException(
                          $"Could not find descriptor for '{fromMethod}', has it been registered yet?  Descriptors must be registered before links can be created!", nameof(fromMethod)
                          );
            }

            LspHandlerDescriptor descriptor = null;

            descriptor = GetDescriptor(
                toMethod,
                source.HandlerType,
                source.Handler,
                source.RequestProcessType.HasValue ? new JsonRpcHandlerOptions {
                RequestProcessType = source.RequestProcessType.Value
            } : null,
                source.TypeDescriptor,
                source.HandlerType,
                source.RegistrationType,
                source.CapabilityType
                );
            Interlocked.Exchange(ref _descriptors, _descriptors.Add(descriptor));
            var cd = new CompositeDisposable();

            if (descriptor.Handler is ITextDocumentIdentifier textDocumentIdentifier)
            {
                cd.Add(_textDocumentIdentifiers.Add(textDocumentIdentifier));
            }

            return(new LspHandlerDescriptorDisposable(new[] { descriptor }, cd));
        }