forked from OmniSharp/csharp-language-server-protocol
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathReceiver.cs
128 lines (108 loc) · 4.27 KB
/
Receiver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using OmniSharp.Extensions.JsonRpc.Server;
using OmniSharp.Extensions.JsonRpc.Server.Messages;
namespace OmniSharp.Extensions.JsonRpc
{
public class Receiver : IReceiver, IOutputFilter
{
protected bool _initialized { get; private set; }
public bool IsValid(JToken container)
{
// request must be an object or array
if (container is JObject)
{
return true;
}
if (container is JArray array)
{
return array.Count > 0;
}
return false;
}
public void Initialized() => _initialized = true;
public virtual (IEnumerable<Renor> results, bool hasResponse) GetRequests(JToken container)
{
var results = new List<Renor>();
if (container is JArray)
{
results.AddRange(container.Select(GetRenor));
}
else
{
results.Add(GetRenor(container));
}
return ( results, results.Any(z => z.IsResponse) );
}
protected virtual Renor GetRenor(JToken @object)
{
if (!( @object is JObject request ))
{
return new InvalidRequest(null, "Not an object");
}
var protocol = request["jsonrpc"]?.Value<string>();
if (protocol != "2.0")
{
return new InvalidRequest(null, "Unexpected protocol");
}
object? requestId = null;
bool hasRequestId;
// ReSharper disable once AssignmentInConditionalExpression
if (hasRequestId = request.TryGetValue("id", out var id))
{
var idString = id.Type == JTokenType.String ? (string) id : null;
var idLong = id.Type == JTokenType.Integer ? (long?) id : null;
requestId = idString ?? ( idLong.HasValue ? (object) idLong.Value : null );
}
if (hasRequestId && request.TryGetValue("result", out var response))
{
return new ServerResponse(requestId!, response);
}
if (request.TryGetValue("error", out var errorResponse))
{
// TODO: this doesn't seem right.
return new ServerError(requestId, errorResponse.ToObject<ServerErrorResult>());
}
var method = request["method"]?.Value<string>();
if (string.IsNullOrEmpty(method))
{
return new InvalidRequest(requestId, string.Empty, "Method not set");
}
var hasParams = request.TryGetValue("params", out var @params);
if (hasParams && @params?.Type != JTokenType.Array && @params?.Type != JTokenType.Object && @params?.Type != JTokenType.Null)
{
return new InvalidRequest(requestId, method, "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)
{
@params = new JObject();
}
var properties = request.Properties().ToLookup(z => z.Name, StringComparer.OrdinalIgnoreCase);
var traceStateProperty = properties["tracestate"].FirstOrDefault();
var traceState = traceStateProperty?.Value.ToString();
var traceParentProperty = properties["traceparent"].FirstOrDefault();
var traceParent = traceParentProperty?.Value.ToString();
// id == request
// !id == notification
if (!hasRequestId)
{
return new Notification(method!, @params) {
TraceState = traceState,
TraceParent = traceParent,
};
}
else
{
return new Request(requestId!, method!, @params) {
TraceState = traceState,
TraceParent = traceParent,
};
}
}
public bool ShouldOutput(object value) => _initialized;
}
}