Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/JsonRpc/Reciever.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,18 @@ protected virtual Renor GetRenor(JToken @object)
}

var hasParams = request.TryGetValue("params", out var @params);
if (hasParams && @params?.Type != JTokenType.Array && @params?.Type != JTokenType.Object)
if (hasParams && @params?.Type != JTokenType.Array && @params?.Type != JTokenType.Object && @params?.Type != JTokenType.Null)
{
return new InvalidRequest(requestId, "Invalid params");
}

// Special case params such that if we get a null value (from a non spec compliant system)
// that we don't fall over and throw an error.
if (@params?.Type == JTokenType.Null)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch - I would have forgotten to do this bit :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we don't want to try to deserialize the value.

{
@params = null;
}

// id == request
// !id == notification
if (!hasRequestId)
Expand Down
2 changes: 1 addition & 1 deletion src/Protocol/General/IShutdownHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ public static partial class GeneralNames
}

[Serial, Method(Shutdown)]
public interface IShutdownHandler : INotificationHandler { }
public interface IShutdownHandler : IRequestHandler<object> { }
}
18 changes: 9 additions & 9 deletions src/Server/Handlers/ShutdownHandler.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Threading;
using System.Threading.Tasks;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Server.Abstractions;
Expand All @@ -6,19 +7,18 @@ namespace OmniSharp.Extensions.LanguageServer.Server.Handlers
{
public class ShutdownHandler : IShutdownHandler, IAwaitableTermination
{
public Task Handle()
public event ShutdownEventHandler Shutdown;

public bool ShutdownRequested { get; private set; }

private readonly TaskCompletionSource<bool> _shutdownSource = new TaskCompletionSource<bool>(TaskContinuationOptions.LongRunning);
Task IAwaitableTermination.WasShutDown => _shutdownSource.Task;
public Task Handle(object request, CancellationToken token)
{
ShutdownRequested = true;
Shutdown?.Invoke(ShutdownRequested);
shutdownSource.SetResult(true); // after all event sinks were notified
_shutdownSource.SetResult(true); // after all event sinks were notified
return Task.CompletedTask;
}

public event ShutdownEventHandler Shutdown;

public bool ShutdownRequested { get; private set; }

private readonly TaskCompletionSource<bool> shutdownSource = new TaskCompletionSource<bool>(TaskContinuationOptions.LongRunning);
Task IAwaitableTermination.WasShutDown => shutdownSource.Task;
}
}
33 changes: 31 additions & 2 deletions test/JsonRpc.Tests/Server/SpecifictionRecieverTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
Expand Down Expand Up @@ -56,6 +56,24 @@ public override IEnumerable<ValueTuple<string, Renor[]>> GetValues()
new Request(4, "subtract", JObject.FromObject(new {minuend = 42, subtrahend = 23}))
});

yield return (
@"{""jsonrpc"": ""2.0"", ""method"": ""subtract"", ""id"": 4}",
new Renor[]
{
new Request(4, "subtract", null)
});

// http://www.jsonrpc.org/specification says:
// If present, parameters for the rpc call MUST be provided as a Structured value.
// Some clients may serialize params as null, instead of omitting it
// We're going to pretend we never got the null in the first place.
yield return (
@"{""jsonrpc"": ""2.0"", ""method"": ""subtract"", ""params"": null, ""id"": 4}",
new Renor[]
{
new Request(4, "subtract", null)
});

yield return (
@"{""jsonrpc"": ""2.0"", ""method"": ""update"", ""params"": [1,2,3,4,5]}",
new Renor[]
Expand All @@ -70,6 +88,17 @@ public override IEnumerable<ValueTuple<string, Renor[]>> GetValues()
new Notification("foobar", null)
});

// http://www.jsonrpc.org/specification says:
// If present, parameters for the rpc call MUST be provided as a Structured value.
// Some clients may serialize params as null, instead of omitting it
// We're going to pretend we never got the null in the first place.
yield return (
@"{""jsonrpc"": ""2.0"", ""method"": ""foobar"", ""params"": null}",
new Renor[]
{
new Notification("foobar", null)
});

yield return (
@"{""jsonrpc"": ""2.0"", ""method"": 1, ""params"": ""bar""}",
new Renor[]
Expand Down Expand Up @@ -144,4 +173,4 @@ public override IEnumerable<ValueTuple<string, bool>> GetValues()
}
}
}
}
}