diff --git a/src/JsonRpc/Pipelines/RequestMustNotBeNullProcessor.cs b/src/JsonRpc/Pipelines/RequestMustNotBeNullProcessor.cs new file mode 100644 index 000000000..451cdd9d4 --- /dev/null +++ b/src/JsonRpc/Pipelines/RequestMustNotBeNullProcessor.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace OmniSharp.Extensions.JsonRpc.Pipelines +{ + public class RequestMustNotBeNullProcessor : MediatR.Pipeline.IRequestPreProcessor + { + public Task Process(T request, CancellationToken cancellationToken) + { + if (typeof(T).IsClass && EqualityComparer.Default.Equals(request, default)) + throw new ArgumentNullException(nameof(request), $"Pipeline request ({typeof(T).FullName}) must not be null"); + return Task.CompletedTask; + } + } +} diff --git a/src/JsonRpc/Pipelines/ResponseMustNotBeNullProcessor.cs b/src/JsonRpc/Pipelines/ResponseMustNotBeNullProcessor.cs new file mode 100644 index 000000000..fc91e2cf2 --- /dev/null +++ b/src/JsonRpc/Pipelines/ResponseMustNotBeNullProcessor.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace OmniSharp.Extensions.JsonRpc.Pipelines +{ + public class ResponseMustNotBeNullProcessor : MediatR.Pipeline.IRequestPostProcessor + { + public Task Process(T request, R response, CancellationToken cancellationToken) + { + if (typeof(R).IsClass && EqualityComparer.Default.Equals(response, default)) + throw new ArgumentNullException(nameof(request), $"Pipeline response ({typeof(R).FullName}) must not be null"); + return Task.CompletedTask; + } + } +} diff --git a/src/JsonRpc/ServiceCollectionExtensions.cs b/src/JsonRpc/ServiceCollectionExtensions.cs index 50167c35d..a9e440028 100644 --- a/src/JsonRpc/ServiceCollectionExtensions.cs +++ b/src/JsonRpc/ServiceCollectionExtensions.cs @@ -2,9 +2,11 @@ using System.Collections.Generic; using System.Reflection; using MediatR; +using MediatR.Pipeline; using MediatR.Registration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using OmniSharp.Extensions.JsonRpc.Pipelines; namespace OmniSharp.Extensions.JsonRpc { @@ -14,13 +16,11 @@ public static IServiceCollection AddJsonRpcMediatR(this IServiceCollection servi { ServiceRegistrar.AddRequiredServices(services, new MediatRServiceConfiguration()); ServiceRegistrar.AddMediatRClasses(services, assemblies); + services.AddTransient(typeof(IRequestPreProcessor<>), typeof(RequestMustNotBeNullProcessor<>)); + services.AddTransient(typeof(IRequestPostProcessor<,>), typeof(ResponseMustNotBeNullProcessor<,>)); services.AddScoped(); services.RemoveAll(); - services.AddScoped( - serviceProvider => { - return serviceType => GetHandler(serviceProvider, serviceType); - } - ); + services.AddScoped(serviceProvider => { return serviceType => GetHandler(serviceProvider, serviceType); }); return services; } @@ -32,6 +32,7 @@ private static object GetHandler(IServiceProvider serviceProvider, Type serviceT var context = serviceProvider.GetService(); return context.Descriptor != null ? context.Descriptor.Handler : serviceProvider.GetService(serviceType); } + return serviceProvider.GetService(serviceType); } } diff --git a/test/JsonRpc.Tests/IntegrationTests.cs b/test/JsonRpc.Tests/IntegrationTests.cs index 31e82b897..f60eed6a1 100644 --- a/test/JsonRpc.Tests/IntegrationTests.cs +++ b/test/JsonRpc.Tests/IntegrationTests.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; +using MediatR; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.JsonRpc.Server; using OmniSharp.Extensions.JsonRpc.Testing; @@ -17,6 +18,11 @@ public IntegrationTests() : base(new JsonRpcTestOptions()) { } + class Request : IRequest + { + + } + class Data { public string Value { get; set; } @@ -37,6 +43,36 @@ public async Task Should_Send_and_receive_requests() clientResponse.Value.Should().Be("myresponse"); } + [Fact] + public async Task Should_throw_when_sending_requests() + { + var (client, server) = await Initialize( + client => { client.OnRequest("myrequest", async (Request request) => new Data() {Value = "myresponse"}); }, + server => { server.OnRequest("myrequest", async (Request request) => new Data() {Value = string.Join("", "myresponse".Reverse())}); } + ); + + Func clientRequest = () => client.SendRequest("myrequest", (Request)null).Returning(CancellationToken); + clientRequest.Should().Throw(); + + Func serverRequest = () => server.SendRequest("myrequest", (Request)null).Returning(CancellationToken); + serverRequest.Should().Throw(); + } + + [Fact] + public async Task Should_throw_when_receiving_requests() + { + var (client, server) = await Initialize( + client => { client.OnRequest("myrequest", async (Request request) => (Data)null); }, + server => { server.OnRequest("myrequest", async (Request request) => (Data)null); } + ); + + Func clientRequest = () => client.SendRequest("myrequest", new Request()).Returning(CancellationToken); + clientRequest.Should().Throw(); + + Func serverRequest = () => server.SendRequest("myrequest", new Request()).Returning(CancellationToken); + serverRequest.Should().Throw(); + } + [Fact] public async Task Should_Send_and_receive_notifications() { diff --git a/test/coverage/Client-Tests/coverage.netcoreapp2.1.info b/test/coverage/Client-Tests/coverage.netcoreapp2.1.info deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/coverage/Client-Tests/coverage.netcoreapp2.1.json b/test/coverage/Client-Tests/coverage.netcoreapp2.1.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/test/coverage/Client-Tests/coverage.netcoreapp2.1.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/coverage/Client-Tests/coverage.netcoreapp3.1.info b/test/coverage/Client-Tests/coverage.netcoreapp3.1.info deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/coverage/Client-Tests/coverage.netcoreapp3.1.json b/test/coverage/Client-Tests/coverage.netcoreapp3.1.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/test/coverage/Client-Tests/coverage.netcoreapp3.1.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/coverage/Dap-Tests/coverage.netcoreapp2.1.info b/test/coverage/Dap-Tests/coverage.netcoreapp2.1.info deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/coverage/Dap-Tests/coverage.netcoreapp2.1.json b/test/coverage/Dap-Tests/coverage.netcoreapp2.1.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/test/coverage/Dap-Tests/coverage.netcoreapp2.1.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/coverage/Dap-Tests/coverage.netcoreapp3.1.info b/test/coverage/Dap-Tests/coverage.netcoreapp3.1.info deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/coverage/Dap-Tests/coverage.netcoreapp3.1.json b/test/coverage/Dap-Tests/coverage.netcoreapp3.1.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/test/coverage/Dap-Tests/coverage.netcoreapp3.1.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/coverage/Generation-Tests/coverage.netcoreapp2.1.info b/test/coverage/Generation-Tests/coverage.netcoreapp2.1.info deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/coverage/Generation-Tests/coverage.netcoreapp2.1.json b/test/coverage/Generation-Tests/coverage.netcoreapp2.1.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/test/coverage/Generation-Tests/coverage.netcoreapp2.1.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/coverage/Generation-Tests/coverage.netcoreapp3.1.info b/test/coverage/Generation-Tests/coverage.netcoreapp3.1.info deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/coverage/Generation-Tests/coverage.netcoreapp3.1.json b/test/coverage/Generation-Tests/coverage.netcoreapp3.1.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/test/coverage/Generation-Tests/coverage.netcoreapp3.1.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/coverage/JsonRpc-Tests/coverage.netcoreapp2.1.info b/test/coverage/JsonRpc-Tests/coverage.netcoreapp2.1.info deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/coverage/JsonRpc-Tests/coverage.netcoreapp2.1.json b/test/coverage/JsonRpc-Tests/coverage.netcoreapp2.1.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/test/coverage/JsonRpc-Tests/coverage.netcoreapp2.1.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/coverage/JsonRpc-Tests/coverage.netcoreapp3.1.info b/test/coverage/JsonRpc-Tests/coverage.netcoreapp3.1.info deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/coverage/JsonRpc-Tests/coverage.netcoreapp3.1.json b/test/coverage/JsonRpc-Tests/coverage.netcoreapp3.1.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/test/coverage/JsonRpc-Tests/coverage.netcoreapp3.1.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file