@@ -19,10 +19,12 @@ import type * as rpc from 'vscode-jsonrpc';
1919import type * as lsp from 'vscode-languageserver-protocol' ;
2020import type { MessageConnection } from 'vscode-ws-jsonrpc' ;
2121
22+ import { ILSPLogConsole } from './tokens' ;
2223import { until_ready } from './utils' ;
2324
2425interface ILSPOptions extends ILspOptions {
2526 serverIdentifier ?: string ;
27+ console : ILSPLogConsole ;
2628}
2729
2830/**
@@ -49,7 +51,7 @@ export namespace Method {
4951 }
5052
5153 /** Server requests */
52- export enum ServerRequests {
54+ export enum ServerRequest {
5355 REGISTER_CAPABILITY = 'client/registerCapability' ,
5456 SHOW_MESSAGE_REQUEST = 'window/showMessageRequest' ,
5557 UNREGISTER_CAPABILITY = 'client/unregisterCapability'
@@ -90,15 +92,15 @@ export interface IClientNotifyParams {
9092}
9193
9294export 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 ;
9698}
9799
98100export 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 ;
102104}
103105
104106export interface IClientRequestParams {
@@ -134,14 +136,14 @@ export interface IClientResult {
134136export type ServerNotifications <
135137 T extends keyof IServerNotifyParams = keyof IServerNotifyParams
136138> = {
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.
138140 [ key in T ] : ISignal < LSPConnection , IServerNotifyParams [ key ] > ;
139141} ;
140142
141143export type ClientNotifications <
142144 T extends keyof IClientNotifyParams = keyof IClientNotifyParams
143145> = {
144- // Signal has emit.
146+ readonly // Signal has emit.
145147 [ key in T ] : Signal < LSPConnection , IClientNotifyParams [ key ] > ;
146148} ;
147149
@@ -166,23 +168,39 @@ export interface IServerRequestHandler<
166168export type ClientRequests <
167169 T extends keyof IClientRequestParams = keyof IClientRequestParams
168170> = {
169- // has async request(params) returning a promise with result.
171+ readonly // has async request(params) returning a promise with result.
170172 [ key in T ] : IClientRequestHandler < key > ;
171173} ;
172174
173175export type ServerRequests <
174176 T extends keyof IServerRequestParams = keyof IServerRequestParams
175177> = {
176- // has async request(params) returning a promise with result.
178+ readonly // has async request(params) returning a promise with result.
177179 [ key in T ] : IServerRequestHandler < key > ;
178180} ;
179181
180182class ClientRequestHandler <
181183 T extends keyof IClientRequestParams = keyof IClientRequestParams
182184> 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+ ) { }
184190 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+ } ) ;
186204 }
187205}
188206
@@ -205,10 +223,20 @@ class ServerRequestHandler<
205223 }
206224
207225 private handle ( request : IServerRequestParams [ T ] ) : Promise < IServerResult [ T ] > {
226+ this . emitter . log ( MessageKind . server_requested , {
227+ method : this . method ,
228+ message : request
229+ } ) ;
208230 if ( ! this . _handler ) {
209231 return ;
210232 }
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+ } ) ;
212240 }
213241
214242 setHandler (
@@ -252,67 +280,104 @@ export const Provider: { [key: string]: keyof lsp.ServerCapabilities } = {
252280 WORKSPACE : 'workspace'
253281} ;
254282
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+
255319export class LSPConnection extends LspWsConnection {
256320 protected documentsToOpen : IDocumentInfo [ ] ;
257321 public serverIdentifier : string ;
258322
259- public serverNotifications : ServerNotifications ;
260323 public clientNotifications : ClientNotifications ;
324+ public serverNotifications : ServerNotifications ;
261325 public clientRequests : ClientRequests ;
262326 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+ }
263335
264336 protected constructNotificationHandlers <
265- T extends ServerNotifications | ClientNotifications ,
266- U extends keyof T = keyof T
337+ T extends ServerNotifications | ClientNotifications
267338 > (
268339 methods : typeof Method . ServerNotification | typeof Method . ClientNotification
269340 ) {
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+ ) ;
275345 }
276346
277347 protected constructClientRequestHandler <
278348 T extends ClientRequests ,
279349 U extends keyof T = keyof T
280350 > ( 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+ ) ;
289356 }
290357
291358 protected constructServerRequestHandler <
292359 T extends ServerRequests ,
293360 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+ ) ;
304367 }
305368
306369 constructor ( options : ILSPOptions ) {
307370 super ( options ) ;
371+ this . logAllCommunication = false ;
308372 this . serverIdentifier = options ?. serverIdentifier ;
373+ this . console = options . console . scope ( this . serverIdentifier + ' connection' ) ;
309374 this . documentsToOpen = [ ] ;
310- this . serverNotifications = this . constructNotificationHandlers <
311- ServerNotifications
312- > ( Method . ServerNotification ) ;
313375 this . clientNotifications = this . constructNotificationHandlers <
314376 ClientNotifications
315377 > ( Method . ClientNotification ) ;
378+ this . serverNotifications = this . constructNotificationHandlers <
379+ ServerNotifications
380+ > ( Method . ServerNotification ) ;
316381 }
317382
318383 sendOpenWhenReady ( documentInfo : IDocumentInfo ) {
@@ -323,18 +388,12 @@ export class LSPConnection extends LspWsConnection {
323388 }
324389 }
325390
326- sendInitialize ( ) {
327- super . sendInitialize ( ) ;
328- }
329-
330391 protected onServerInitialized ( params : lsp . InitializeResult ) {
392+ this . afterInitialized ( ) ;
331393 super . onServerInitialized ( params ) ;
332394 while ( this . documentsToOpen . length ) {
333395 this . sendOpen ( this . documentsToOpen . pop ( ) ) ;
334396 }
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 ( ) ;
338397 }
339398
340399 protected afterInitialized ( ) {
@@ -343,6 +402,10 @@ export class LSPConnection extends LspWsConnection {
343402 ) as ( keyof ServerNotifications ) [ ] ) {
344403 const signal = this . serverNotifications [ method ] as Signal < any , any > ;
345404 this . connection . onNotification ( method , params => {
405+ this . log ( MessageKind . server_notified_client , {
406+ method,
407+ message : params
408+ } ) ;
346409 signal . emit ( params ) ;
347410 } ) ;
348411 }
@@ -352,6 +415,10 @@ export class LSPConnection extends LspWsConnection {
352415 ) as ( keyof ClientNotifications ) [ ] ) {
353416 const signal = this . clientNotifications [ method ] as Signal < any , any > ;
354417 signal . connect ( ( emitter , params ) => {
418+ this . log ( MessageKind . client_notified_server , {
419+ method,
420+ message : params
421+ } ) ;
355422 this . connection . sendNotification ( method , params ) ;
356423 } ) ;
357424 }
@@ -360,7 +427,7 @@ export class LSPConnection extends LspWsConnection {
360427 Method . ClientRequest
361428 ) ;
362429 this . serverRequests = this . constructServerRequestHandler < ServerRequests > (
363- Method . ServerRequests
430+ Method . ServerRequest
364431 ) ;
365432
366433 this . serverRequests [ 'client/registerCapability' ] . setHandler (
@@ -377,8 +444,6 @@ export class LSPConnection extends LspWsConnection {
377444 }
378445 }
379446 ) ;
380-
381- // TODO log event
382447 }
383448 ) ;
384449
@@ -392,8 +457,6 @@ export class LSPConnection extends LspWsConnection {
392457 ) ;
393458 }
394459 ) ;
395-
396- // TODO log event
397460 }
398461 ) ;
399462 }
0 commit comments