Skip to content

Commit eb09697

Browse files
Refactored IResponseRouter for better type inference (#235)
+semver:minor
1 parent 79b1056 commit eb09697

File tree

7 files changed

+97
-132
lines changed

7 files changed

+97
-132
lines changed

src/JsonRpc/IResponseRouter.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@ public interface IResponseRouter
99
{
1010
void SendNotification(string method);
1111
void SendNotification<T>(string method, T @params);
12-
void SendNotification(IRequest @params);
13-
Task<TResponse> SendRequest<T, TResponse>(string method, T @params, CancellationToken cancellationToken);
14-
Task<TResponse> SendRequest<TResponse>(IRequest<TResponse> @params, CancellationToken cancellationToken);
15-
Task SendRequest(IRequest @params, CancellationToken cancellationToken);
16-
Task<TResponse> SendRequest<TResponse>(string method, CancellationToken cancellationToken);
17-
Task SendRequest<T>(string method, T @params, CancellationToken cancellationToken);
12+
void SendNotification(IRequest request);
13+
IResponseRouterReturns SendRequest<T>(string method, T @params);
14+
IResponseRouterReturns SendRequest(string method);
15+
Task<TResponse> SendRequest<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken);
1816
TaskCompletionSource<JToken> GetRequest(long id);
1917
}
2018
}

src/JsonRpc/IReturning.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
4+
namespace OmniSharp.Extensions.JsonRpc
5+
{
6+
public interface IResponseRouterReturns
7+
{
8+
Task<TResponse> Returning<TResponse>(CancellationToken cancellationToken);
9+
Task ReturningVoid(CancellationToken cancellationToken);
10+
}
11+
}

src/JsonRpc/JsonRpcServer.cs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -197,29 +197,19 @@ public void SendNotification(IRequest @params)
197197
_responseRouter.SendNotification(@params);
198198
}
199199

200-
public Task<TResponse> SendRequest<T, TResponse>(string method, T @params, CancellationToken cancellationToken)
201-
{
202-
return _responseRouter.SendRequest<T, TResponse>(method, @params, cancellationToken);
203-
}
204-
205200
public Task<TResponse> SendRequest<TResponse>(IRequest<TResponse> @params, CancellationToken cancellationToken)
206201
{
207202
return _responseRouter.SendRequest(@params, cancellationToken);
208203
}
209204

210-
public Task SendRequest(IRequest @params, CancellationToken cancellationToken)
211-
{
212-
return _responseRouter.SendRequest(@params, cancellationToken);
213-
}
214-
215-
public Task<TResponse> SendRequest<TResponse>(string method, CancellationToken cancellationToken)
205+
public IResponseRouterReturns SendRequest<T>(string method, T @params)
216206
{
217-
return _responseRouter.SendRequest<TResponse>(method, cancellationToken);
207+
return _responseRouter.SendRequest<T>(method, @params);
218208
}
219209

220-
public Task SendRequest<T>(string method, T @params, CancellationToken cancellationToken)
210+
public IResponseRouterReturns SendRequest(string method)
221211
{
222-
return _responseRouter.SendRequest(method, @params, cancellationToken);
212+
return _responseRouter.SendRequest(method);
223213
}
224214

225215
public TaskCompletionSource<JToken> GetRequest(long id)

src/JsonRpc/ResponseRouter.cs

Lines changed: 67 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,31 @@ namespace OmniSharp.Extensions.JsonRpc
1010
{
1111
public class ResponseRouter : IResponseRouter
1212
{
13-
private readonly IOutputHandler _outputHandler;
14-
private readonly ISerializer _serializer;
15-
private readonly object _lock = new object();
16-
private readonly ConcurrentDictionary<long, TaskCompletionSource<JToken>> _requests = new ConcurrentDictionary<long, TaskCompletionSource<JToken>>();
17-
private static readonly ConcurrentDictionary<Type, string> _methodCache = new ConcurrentDictionary<Type, string>();
13+
internal readonly IOutputHandler OutputHandler;
14+
internal readonly ISerializer Serializer;
15+
16+
internal readonly ConcurrentDictionary<long, TaskCompletionSource<JToken>> Requests =
17+
new ConcurrentDictionary<long, TaskCompletionSource<JToken>>();
18+
19+
internal static readonly ConcurrentDictionary<Type, string> MethodCache =
20+
new ConcurrentDictionary<Type, string>();
1821

1922
public ResponseRouter(IOutputHandler outputHandler, ISerializer serializer)
2023
{
21-
_outputHandler = outputHandler;
22-
_serializer = serializer;
24+
OutputHandler = outputHandler;
25+
Serializer = serializer;
2326
}
2427

2528
public void SendNotification(string method)
2629
{
27-
_outputHandler.Send(new Client.Notification() {
30+
OutputHandler.Send(new Client.Notification() {
2831
Method = method
2932
}, CancellationToken.None);
3033
}
3134

3235
public void SendNotification<T>(string method, T @params)
3336
{
34-
_outputHandler.Send(new Client.Notification() {
37+
OutputHandler.Send(new Client.Notification() {
3538
Method = method,
3639
Params = @params
3740
}, CancellationToken.None);
@@ -42,100 +45,30 @@ public void SendNotification(IRequest @params)
4245
SendNotification(GetMethodName(@params.GetType()), @params);
4346
}
4447

45-
public async Task<TResponse> SendRequest<T, TResponse>(string method, T @params, CancellationToken cancellationToken)
46-
{
47-
var tcs = new TaskCompletionSource<JToken>();
48-
49-
var nextId = _serializer.GetNextId();
50-
_requests.TryAdd(nextId, tcs);
51-
52-
_outputHandler.Send(new Client.Request() {
53-
Method = method,
54-
Params = @params,
55-
Id = nextId
56-
}, cancellationToken);
57-
58-
try
59-
{
60-
var result = await tcs.Task;
61-
if (typeof(TResponse) == typeof(Unit))
62-
{
63-
return (TResponse)(object)Unit.Value;
64-
}
65-
return result.ToObject<TResponse>(_serializer.JsonSerializer);
66-
}
67-
finally
68-
{
69-
_requests.TryRemove(nextId, out _);
70-
}
71-
}
72-
7348
public Task<TResponse> SendRequest<TResponse>(IRequest<TResponse> @params, CancellationToken cancellationToken)
7449
{
75-
return SendRequest<IRequest<TResponse>, TResponse>(GetMethodName(@params.GetType()), @params, cancellationToken);
50+
return SendRequest(GetMethodName(@params.GetType()), @params).Returning<TResponse>(cancellationToken);
7651
}
7752

78-
public Task SendRequest(IRequest @params, CancellationToken cancellationToken)
53+
public IResponseRouterReturns SendRequest(string method)
7954
{
80-
return SendRequest(GetMethodName(@params.GetType()), @params, cancellationToken);
55+
return new ResponseRouterReturnsImpl(this, method, null);
8156
}
8257

83-
public async Task<TResponse> SendRequest<TResponse>(string method, CancellationToken cancellationToken)
58+
public IResponseRouterReturns SendRequest<T>(string method, T @params)
8459
{
85-
var nextId = _serializer.GetNextId();
86-
87-
var tcs = new TaskCompletionSource<JToken>();
88-
_requests.TryAdd(nextId, tcs);
89-
90-
_outputHandler.Send(new Client.Request() {
91-
Method = method,
92-
Params = null,
93-
Id = nextId
94-
}, cancellationToken);
95-
96-
try
97-
{
98-
var result = await tcs.Task;
99-
return result.ToObject<TResponse>(_serializer.JsonSerializer);
100-
}
101-
finally
102-
{
103-
_requests.TryRemove(nextId, out var _);
104-
}
105-
}
106-
107-
public async Task SendRequest<T>(string method, T @params, CancellationToken cancellationToken)
108-
{
109-
var nextId = _serializer.GetNextId();
110-
111-
var tcs = new TaskCompletionSource<JToken>();
112-
_requests.TryAdd(nextId, tcs);
113-
114-
_outputHandler.Send(new Client.Request() {
115-
Method = method,
116-
Params = @params,
117-
Id = nextId
118-
}, cancellationToken);
119-
120-
try
121-
{
122-
await tcs.Task;
123-
}
124-
finally
125-
{
126-
_requests.TryRemove(nextId, out var _);
127-
}
60+
return new ResponseRouterReturnsImpl(this, method, @params);
12861
}
12962

13063
public TaskCompletionSource<JToken> GetRequest(long id)
13164
{
132-
_requests.TryGetValue(id, out var source);
65+
Requests.TryGetValue(id, out var source);
13366
return source;
13467
}
13568

13669
private string GetMethodName(Type type)
13770
{
138-
if (!_methodCache.TryGetValue(type, out var methodName))
71+
if (!MethodCache.TryGetValue(type, out var methodName))
13972
{
14073
var attribute = type.GetCustomAttribute<MethodAttribute>(true);
14174
if (attribute == null)
@@ -144,10 +77,57 @@ private string GetMethodName(Type type)
14477
}
14578

14679
methodName = attribute.Method;
147-
_methodCache.TryAdd(type, methodName);
80+
MethodCache.TryAdd(type, methodName);
14881
}
14982

15083
return methodName;
15184
}
85+
86+
class ResponseRouterReturnsImpl : IResponseRouterReturns
87+
{
88+
private readonly ResponseRouter _router;
89+
private readonly string _method;
90+
private readonly object _params;
91+
92+
public ResponseRouterReturnsImpl(ResponseRouter router, string method, object @params)
93+
{
94+
_router = router;
95+
_method = method;
96+
_params = @params;
97+
}
98+
99+
public async Task<TResponse> Returning<TResponse>(CancellationToken cancellationToken)
100+
{
101+
var nextId = _router.Serializer.GetNextId();
102+
var tcs = new TaskCompletionSource<JToken>();
103+
_router.Requests.TryAdd(nextId, tcs);
104+
105+
_router.OutputHandler.Send(new Client.Request() {
106+
Method = _method,
107+
Params = _params,
108+
Id = nextId
109+
}, cancellationToken);
110+
111+
try
112+
{
113+
var result = await tcs.Task;
114+
if (typeof(TResponse) == typeof(Unit))
115+
{
116+
return (TResponse) (object) Unit.Value;
117+
}
118+
119+
return result.ToObject<TResponse>(_router.Serializer.JsonSerializer);
120+
}
121+
finally
122+
{
123+
_router.Requests.TryRemove(nextId, out var _);
124+
}
125+
}
126+
127+
public async Task ReturningVoid(CancellationToken cancellationToken)
128+
{
129+
await Returning<Unit>(cancellationToken);
130+
}
131+
}
152132
}
153133
}

src/Protocol/ClientProxyBase.cs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,14 @@ public ClientProxyBase(IResponseRouter responseRouter)
1717
public void SendNotification(string method) => _responseRouter.SendNotification(method);
1818

1919
public void SendNotification<T>(string method, T @params) => _responseRouter.SendNotification(method, @params);
20-
public void SendNotification(IRequest @params) => _responseRouter.SendNotification(@params);
2120

22-
public Task<TResponse> SendRequest<T, TResponse>(string method, T @params, CancellationToken cancellationToken) => _responseRouter.SendRequest<T, TResponse>(method, @params, cancellationToken);
23-
public Task<TResponse> SendRequest<TResponse>(IRequest<TResponse> @params, CancellationToken cancellationToken) => _responseRouter.SendRequest(@params, cancellationToken);
24-
public Task SendRequest(IRequest @params, CancellationToken cancellationToken)
25-
{
26-
return _responseRouter.SendRequest(@params, cancellationToken);
27-
}
21+
public void SendNotification(IRequest request) => _responseRouter.SendNotification(request);
22+
23+
public IResponseRouterReturns SendRequest<T>(string method, T @params) => _responseRouter.SendRequest(method, @params);
2824

29-
public Task<TResponse> SendRequest<TResponse>(string method, CancellationToken cancellationToken) => _responseRouter.SendRequest<TResponse>(method, cancellationToken);
25+
public IResponseRouterReturns SendRequest(string method) => _responseRouter.SendRequest(method);
3026

31-
public Task SendRequest<T>(string method, T @params, CancellationToken cancellationToken ) => _responseRouter.SendRequest(method, @params, cancellationToken);
27+
public Task<TResponse> SendRequest<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken) => _responseRouter.SendRequest(request, cancellationToken);
3228

3329
public TaskCompletionSource<JToken> GetRequest(long id) => _responseRouter.GetRequest(id);
3430
}

src/Protocol/Workspace/Client/ExecuteCommandExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public static class ExecuteCommandExtensions
99
{
1010
public static Task ExecuteCommand(this ILanguageClientWorkspace router, ExecuteCommandParams @params, CancellationToken cancellationToken = default)
1111
{
12-
return router.SendRequest(WorkspaceNames.ExecuteCommand, @params, cancellationToken);
12+
return router.SendRequest(@params, cancellationToken);
1313
}
1414
}
1515
}

src/Server/LanguageServer.cs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -665,31 +665,21 @@ public void SendNotification(IRequest @params)
665665
_responseRouter.SendNotification(@params);
666666
}
667667

668-
public Task<TResponse> SendRequest<T, TResponse>(string method, T @params, CancellationToken cancellationToken)
668+
public IResponseRouterReturns SendRequest(string method)
669669
{
670-
return _responseRouter.SendRequest<T, TResponse>(method, @params, cancellationToken);
670+
return _responseRouter.SendRequest(method);
671671
}
672672

673-
public Task<TResponse> SendRequest<TResponse>(IRequest<TResponse> @params, CancellationToken cancellationToken)
673+
public IResponseRouterReturns SendRequest<T>(string method, T @params)
674674
{
675-
return _responseRouter.SendRequest(@params, cancellationToken);
675+
return _responseRouter.SendRequest<T>(method, @params);
676676
}
677677

678-
public Task SendRequest(IRequest @params, CancellationToken cancellationToken)
678+
public Task<TResponse> SendRequest<TResponse>(IRequest<TResponse> @params, CancellationToken cancellationToken)
679679
{
680680
return _responseRouter.SendRequest(@params, cancellationToken);
681681
}
682682

683-
public Task<TResponse> SendRequest<TResponse>(string method, CancellationToken cancellationToken)
684-
{
685-
return _responseRouter.SendRequest<TResponse>(method, cancellationToken);
686-
}
687-
688-
public Task SendRequest<T>(string method, T @params, CancellationToken cancellationToken)
689-
{
690-
return _responseRouter.SendRequest(method, @params, cancellationToken);
691-
}
692-
693683
public TaskCompletionSource<JToken> GetRequest(long id)
694684
{
695685
return _responseRouter.GetRequest(id);

0 commit comments

Comments
 (0)