@@ -19,10 +19,12 @@ import type * as rpc from 'vscode-jsonrpc';
19
19
import type * as lsp from 'vscode-languageserver-protocol' ;
20
20
import type { MessageConnection } from 'vscode-ws-jsonrpc' ;
21
21
22
+ import { ILSPLogConsole } from './tokens' ;
22
23
import { until_ready } from './utils' ;
23
24
24
25
interface ILSPOptions extends ILspOptions {
25
26
serverIdentifier ?: string ;
27
+ console : ILSPLogConsole ;
26
28
}
27
29
28
30
/**
@@ -49,7 +51,7 @@ export namespace Method {
49
51
}
50
52
51
53
/** Server requests */
52
- export enum ServerRequests {
54
+ export enum ServerRequest {
53
55
REGISTER_CAPABILITY = 'client/registerCapability' ,
54
56
SHOW_MESSAGE_REQUEST = 'window/showMessageRequest' ,
55
57
UNREGISTER_CAPABILITY = 'client/unregisterCapability'
@@ -90,15 +92,15 @@ export interface IClientNotifyParams {
90
92
}
91
93
92
94
export interface IServerRequestParams {
93
- [ Method . ServerRequests . REGISTER_CAPABILITY ] : lsp . RegistrationParams ;
94
- [ Method . ServerRequests . SHOW_MESSAGE_REQUEST ] : lsp . ShowMessageRequestParams ;
95
- [ Method . ServerRequests . UNREGISTER_CAPABILITY ] : lsp . UnregistrationParams ;
95
+ [ Method . ServerRequest . REGISTER_CAPABILITY ] : lsp . RegistrationParams ;
96
+ [ Method . ServerRequest . SHOW_MESSAGE_REQUEST ] : lsp . ShowMessageRequestParams ;
97
+ [ Method . ServerRequest . UNREGISTER_CAPABILITY ] : lsp . UnregistrationParams ;
96
98
}
97
99
98
100
export interface IServerResult {
99
- [ Method . ServerRequests . REGISTER_CAPABILITY ] : void ;
100
- [ Method . ServerRequests . SHOW_MESSAGE_REQUEST ] : lsp . MessageActionItem | null ;
101
- [ Method . ServerRequests . UNREGISTER_CAPABILITY ] : void ;
101
+ [ Method . ServerRequest . REGISTER_CAPABILITY ] : void ;
102
+ [ Method . ServerRequest . SHOW_MESSAGE_REQUEST ] : lsp . MessageActionItem | null ;
103
+ [ Method . ServerRequest . UNREGISTER_CAPABILITY ] : void ;
102
104
}
103
105
104
106
export interface IClientRequestParams {
@@ -134,14 +136,14 @@ export interface IClientResult {
134
136
export type ServerNotifications <
135
137
T extends keyof IServerNotifyParams = keyof IServerNotifyParams
136
138
> = {
137
- // ISignal does not have emit, which is intended - client cannot emit server notifications.
139
+ readonly // ISignal does not have emit, which is intended - client cannot emit server notifications.
138
140
[ key in T ] : ISignal < LSPConnection , IServerNotifyParams [ key ] > ;
139
141
} ;
140
142
141
143
export type ClientNotifications <
142
144
T extends keyof IClientNotifyParams = keyof IClientNotifyParams
143
145
> = {
144
- // Signal has emit.
146
+ readonly // Signal has emit.
145
147
[ key in T ] : Signal < LSPConnection , IClientNotifyParams [ key ] > ;
146
148
} ;
147
149
@@ -166,23 +168,39 @@ export interface IServerRequestHandler<
166
168
export type ClientRequests <
167
169
T extends keyof IClientRequestParams = keyof IClientRequestParams
168
170
> = {
169
- // has async request(params) returning a promise with result.
171
+ readonly // has async request(params) returning a promise with result.
170
172
[ key in T ] : IClientRequestHandler < key > ;
171
173
} ;
172
174
173
175
export type ServerRequests <
174
176
T extends keyof IServerRequestParams = keyof IServerRequestParams
175
177
> = {
176
- // has async request(params) returning a promise with result.
178
+ readonly // has async request(params) returning a promise with result.
177
179
[ key in T ] : IServerRequestHandler < key > ;
178
180
} ;
179
181
180
182
class ClientRequestHandler <
181
183
T extends keyof IClientRequestParams = keyof IClientRequestParams
182
184
> implements IClientRequestHandler {
183
- constructor ( protected connection : MessageConnection , protected method : T ) { }
185
+ constructor (
186
+ protected connection : MessageConnection ,
187
+ protected method : T ,
188
+ protected emitter : LSPConnection
189
+ ) { }
184
190
request ( params : IClientRequestParams [ T ] ) : Promise < IClientResult [ T ] > {
185
- return this . connection . sendRequest ( this . method , params ) ;
191
+ this . emitter . log ( MessageKind . client_requested , {
192
+ method : this . method ,
193
+ message : params
194
+ } ) ;
195
+ return this . connection
196
+ . sendRequest ( this . method , params )
197
+ . then ( ( result : IClientResult [ T ] ) => {
198
+ this . emitter . log ( MessageKind . result_for_client , {
199
+ method : this . method ,
200
+ message : params
201
+ } ) ;
202
+ return result ;
203
+ } ) ;
186
204
}
187
205
}
188
206
@@ -205,10 +223,20 @@ class ServerRequestHandler<
205
223
}
206
224
207
225
private handle ( request : IServerRequestParams [ T ] ) : Promise < IServerResult [ T ] > {
226
+ this . emitter . log ( MessageKind . server_requested , {
227
+ method : this . method ,
228
+ message : request
229
+ } ) ;
208
230
if ( ! this . _handler ) {
209
231
return ;
210
232
}
211
- return this . _handler ( request , this . emitter ) ;
233
+ return this . _handler ( request , this . emitter ) . then ( result => {
234
+ this . emitter . log ( MessageKind . response_for_server , {
235
+ method : this . method ,
236
+ message : result
237
+ } ) ;
238
+ return result ;
239
+ } ) ;
212
240
}
213
241
214
242
setHandler (
@@ -252,67 +280,104 @@ export const Provider: { [key: string]: keyof lsp.ServerCapabilities } = {
252
280
WORKSPACE : 'workspace'
253
281
} ;
254
282
283
+ type AnyMethodType =
284
+ | typeof Method . ServerNotification
285
+ | typeof Method . ClientNotification
286
+ | typeof Method . ClientRequest
287
+ | typeof Method . ServerRequest ;
288
+ type AnyMethod =
289
+ | Method . ServerNotification
290
+ | Method . ClientNotification
291
+ | Method . ClientRequest
292
+ | Method . ServerRequest ;
293
+
294
+ function createMethodMap < T , H , U extends keyof T = keyof T > (
295
+ methods : AnyMethodType ,
296
+ handlerFactory : ( method : U ) => H
297
+ ) {
298
+ const result : { [ key in U ] ?: H } = { } ;
299
+ for ( let method of Object . values ( methods ) ) {
300
+ result [ method as U ] = handlerFactory ( method as U ) ;
301
+ }
302
+ return result as T ;
303
+ }
304
+
305
+ enum MessageKind {
306
+ client_notified_server ,
307
+ server_notified_client ,
308
+ server_requested ,
309
+ client_requested ,
310
+ result_for_client ,
311
+ response_for_server
312
+ }
313
+
314
+ interface IMessageLog < T extends AnyMethod = AnyMethod > {
315
+ method : T ;
316
+ message : any ;
317
+ }
318
+
255
319
export class LSPConnection extends LspWsConnection {
256
320
protected documentsToOpen : IDocumentInfo [ ] ;
257
321
public serverIdentifier : string ;
258
322
259
- public serverNotifications : ServerNotifications ;
260
323
public clientNotifications : ClientNotifications ;
324
+ public serverNotifications : ServerNotifications ;
261
325
public clientRequests : ClientRequests ;
262
326
public serverRequests : ServerRequests ;
327
+ protected console : ILSPLogConsole ;
328
+ public logAllCommunication : boolean ;
329
+
330
+ public log ( kind : MessageKind , message : IMessageLog ) {
331
+ if ( this . logAllCommunication ) {
332
+ this . console . log ( kind , message ) ;
333
+ }
334
+ }
263
335
264
336
protected constructNotificationHandlers <
265
- T extends ServerNotifications | ClientNotifications ,
266
- U extends keyof T = keyof T
337
+ T extends ServerNotifications | ClientNotifications
267
338
> (
268
339
methods : typeof Method . ServerNotification | typeof Method . ClientNotification
269
340
) {
270
- const result : { [ key in U ] ?: Signal < any , any > } = { } ;
271
- for ( let method of Object . values ( methods ) ) {
272
- result [ method as U ] = new Signal < any , any > ( this ) ;
273
- }
274
- return result as T ;
341
+ return createMethodMap < T , Signal < any , any > > (
342
+ methods ,
343
+ ( ) => new Signal < any , any > ( this )
344
+ ) ;
275
345
}
276
346
277
347
protected constructClientRequestHandler <
278
348
T extends ClientRequests ,
279
349
U extends keyof T = keyof T
280
350
> ( methods : typeof Method . ClientRequest ) {
281
- const result : { [ key in U ] ?: IClientRequestHandler } = { } ;
282
- for ( let method of Object . values ( methods ) ) {
283
- result [ method as U ] = new ClientRequestHandler (
284
- this . connection ,
285
- ( method as U ) as any
286
- ) ;
287
- }
288
- return result as T ;
351
+ return createMethodMap < T , IClientRequestHandler > (
352
+ methods ,
353
+ method =>
354
+ new ClientRequestHandler ( this . connection , ( method as U ) as any , this )
355
+ ) ;
289
356
}
290
357
291
358
protected constructServerRequestHandler <
292
359
T extends ServerRequests ,
293
360
U extends keyof T = keyof T
294
- > ( methods : typeof Method . ServerRequests ) {
295
- const result : { [ key in U ] ?: IServerRequestHandler } = { } ;
296
- for ( let method of Object . values ( methods ) ) {
297
- result [ method as U ] = new ServerRequestHandler (
298
- this . connection ,
299
- ( method as U ) as any ,
300
- this
301
- ) ;
302
- }
303
- return result as T ;
361
+ > ( methods : typeof Method . ServerRequest ) {
362
+ return createMethodMap < T , IServerRequestHandler > (
363
+ methods ,
364
+ method =>
365
+ new ServerRequestHandler ( this . connection , ( method as U ) as any , this )
366
+ ) ;
304
367
}
305
368
306
369
constructor ( options : ILSPOptions ) {
307
370
super ( options ) ;
371
+ this . logAllCommunication = false ;
308
372
this . serverIdentifier = options ?. serverIdentifier ;
373
+ this . console = options . console . scope ( this . serverIdentifier + ' connection' ) ;
309
374
this . documentsToOpen = [ ] ;
310
- this . serverNotifications = this . constructNotificationHandlers <
311
- ServerNotifications
312
- > ( Method . ServerNotification ) ;
313
375
this . clientNotifications = this . constructNotificationHandlers <
314
376
ClientNotifications
315
377
> ( Method . ClientNotification ) ;
378
+ this . serverNotifications = this . constructNotificationHandlers <
379
+ ServerNotifications
380
+ > ( Method . ServerNotification ) ;
316
381
}
317
382
318
383
sendOpenWhenReady ( documentInfo : IDocumentInfo ) {
@@ -323,18 +388,12 @@ export class LSPConnection extends LspWsConnection {
323
388
}
324
389
}
325
390
326
- sendInitialize ( ) {
327
- super . sendInitialize ( ) ;
328
- }
329
-
330
391
protected onServerInitialized ( params : lsp . InitializeResult ) {
392
+ this . afterInitialized ( ) ;
331
393
super . onServerInitialized ( params ) ;
332
394
while ( this . documentsToOpen . length ) {
333
395
this . sendOpen ( this . documentsToOpen . pop ( ) ) ;
334
396
}
335
- // TODO: move to send Initialize after disabling overwrites in ws-connection
336
- // or maybe move the code there? How to handle logging without bringing in lumino signals?
337
- this . afterInitialized ( ) ;
338
397
}
339
398
340
399
protected afterInitialized ( ) {
@@ -343,6 +402,10 @@ export class LSPConnection extends LspWsConnection {
343
402
) as ( keyof ServerNotifications ) [ ] ) {
344
403
const signal = this . serverNotifications [ method ] as Signal < any , any > ;
345
404
this . connection . onNotification ( method , params => {
405
+ this . log ( MessageKind . server_notified_client , {
406
+ method,
407
+ message : params
408
+ } ) ;
346
409
signal . emit ( params ) ;
347
410
} ) ;
348
411
}
@@ -352,6 +415,10 @@ export class LSPConnection extends LspWsConnection {
352
415
) as ( keyof ClientNotifications ) [ ] ) {
353
416
const signal = this . clientNotifications [ method ] as Signal < any , any > ;
354
417
signal . connect ( ( emitter , params ) => {
418
+ this . log ( MessageKind . client_notified_server , {
419
+ method,
420
+ message : params
421
+ } ) ;
355
422
this . connection . sendNotification ( method , params ) ;
356
423
} ) ;
357
424
}
@@ -360,7 +427,7 @@ export class LSPConnection extends LspWsConnection {
360
427
Method . ClientRequest
361
428
) ;
362
429
this . serverRequests = this . constructServerRequestHandler < ServerRequests > (
363
- Method . ServerRequests
430
+ Method . ServerRequest
364
431
) ;
365
432
366
433
this . serverRequests [ 'client/registerCapability' ] . setHandler (
@@ -377,8 +444,6 @@ export class LSPConnection extends LspWsConnection {
377
444
}
378
445
}
379
446
) ;
380
-
381
- // TODO log event
382
447
}
383
448
) ;
384
449
@@ -392,8 +457,6 @@ export class LSPConnection extends LspWsConnection {
392
457
) ;
393
458
}
394
459
) ;
395
-
396
- // TODO log event
397
460
}
398
461
) ;
399
462
}
0 commit comments