1+ using System ;
12using System . Collections . Concurrent ;
3+ using System . Reflection ;
4+ using System . Threading ;
25using System . Threading . Tasks ;
6+ using MediatR ;
37using Newtonsoft . Json . Linq ;
48
59namespace OmniSharp . Extensions . JsonRpc
@@ -10,6 +14,7 @@ public class ResponseRouter : IResponseRouter
1014 private readonly ISerializer _serializer ;
1115 private readonly object _lock = new object ( ) ;
1216 private readonly ConcurrentDictionary < long , TaskCompletionSource < JToken > > _requests = new ConcurrentDictionary < long , TaskCompletionSource < JToken > > ( ) ;
17+ private static readonly ConcurrentDictionary < Type , string > _methodCache = new ConcurrentDictionary < Type , string > ( ) ;
1318
1419 public ResponseRouter ( IOutputHandler outputHandler , ISerializer serializer )
1520 {
@@ -21,41 +26,61 @@ public void SendNotification(string method)
2126 {
2227 _outputHandler . Send ( new Client . Notification ( ) {
2328 Method = method
24- } ) ;
29+ } , CancellationToken . None ) ;
2530 }
2631
2732 public void SendNotification < T > ( string method , T @params )
2833 {
2934 _outputHandler . Send ( new Client . Notification ( ) {
3035 Method = method ,
3136 Params = @params
32- } ) ;
37+ } , CancellationToken . None ) ;
3338 }
3439
35- public async Task < TResponse > SendRequest < T , TResponse > ( string method , T @params )
40+ public void SendNotification ( IRequest @params )
41+ {
42+ SendNotification ( GetMethodName ( @params . GetType ( ) ) , @params ) ;
43+ }
44+
45+ public async Task < TResponse > SendRequest < T , TResponse > ( string method , T @params , CancellationToken cancellationToken )
3646 {
3747 var tcs = new TaskCompletionSource < JToken > ( ) ;
48+
3849 var nextId = _serializer . GetNextId ( ) ;
3950 _requests . TryAdd ( nextId , tcs ) ;
4051
4152 _outputHandler . Send ( new Client . Request ( ) {
4253 Method = method ,
4354 Params = @params ,
4455 Id = nextId
45- } ) ;
56+ } , cancellationToken ) ;
4657
4758 try
4859 {
4960 var result = await tcs . Task ;
61+ if ( typeof ( TResponse ) == typeof ( Unit ) )
62+ {
63+ return ( TResponse ) ( object ) Unit . Value ;
64+ }
5065 return result . ToObject < TResponse > ( _serializer . JsonSerializer ) ;
5166 }
5267 finally
5368 {
54- _requests . TryRemove ( nextId , out var _ ) ;
69+ _requests . TryRemove ( nextId , out _ ) ;
5570 }
5671 }
5772
58- public async Task < TResponse > SendRequest < TResponse > ( string method )
73+ public Task < TResponse > SendRequest < TResponse > ( IRequest < TResponse > @params , CancellationToken cancellationToken )
74+ {
75+ return SendRequest < IRequest < TResponse > , TResponse > ( GetMethodName ( @params . GetType ( ) ) , @params , cancellationToken ) ;
76+ }
77+
78+ public Task SendRequest ( IRequest @params , CancellationToken cancellationToken )
79+ {
80+ return SendRequest ( GetMethodName ( @params . GetType ( ) ) , @params , cancellationToken ) ;
81+ }
82+
83+ public async Task < TResponse > SendRequest < TResponse > ( string method , CancellationToken cancellationToken )
5984 {
6085 var nextId = _serializer . GetNextId ( ) ;
6186
@@ -66,7 +91,7 @@ public async Task<TResponse> SendRequest<TResponse>(string method)
6691 Method = method ,
6792 Params = null ,
6893 Id = nextId
69- } ) ;
94+ } , cancellationToken ) ;
7095
7196 try
7297 {
@@ -79,7 +104,7 @@ public async Task<TResponse> SendRequest<TResponse>(string method)
79104 }
80105 }
81106
82- public async Task SendRequest < T > ( string method , T @params )
107+ public async Task SendRequest < T > ( string method , T @params , CancellationToken cancellationToken )
83108 {
84109 var nextId = _serializer . GetNextId ( ) ;
85110
@@ -90,7 +115,7 @@ public async Task SendRequest<T>(string method, T @params)
90115 Method = method ,
91116 Params = @params ,
92117 Id = nextId
93- } ) ;
118+ } , cancellationToken ) ;
94119
95120 try
96121 {
@@ -107,5 +132,22 @@ public TaskCompletionSource<JToken> GetRequest(long id)
107132 _requests . TryGetValue ( id , out var source ) ;
108133 return source ;
109134 }
135+
136+ private string GetMethodName ( Type type )
137+ {
138+ if ( ! _methodCache . TryGetValue ( type , out var methodName ) )
139+ {
140+ var attribute = type . GetCustomAttribute < MethodAttribute > ( true ) ;
141+ if ( attribute == null )
142+ {
143+ throw new NotSupportedException ( $ "Unable to infer method name for type { type . FullName } ") ;
144+ }
145+
146+ methodName = attribute . Method ;
147+ _methodCache . TryAdd ( type , methodName ) ;
148+ }
149+
150+ return methodName ;
151+ }
110152 }
111153}
0 commit comments