@@ -3,6 +3,9 @@ set cpoptions&vim
3
3
4
4
let s: clients = {} " { client_id: ctx }
5
5
6
+ " Vars used by native lsp
7
+ let s: jobidseq = 0
8
+
6
9
function ! s: create_context (client_id, opts) abort
7
10
if a: client_id <= 0
8
11
return {}
@@ -212,9 +215,7 @@ let s:send_type_notification = 2
212
215
let s: send_type_response = 3
213
216
function ! s: lsp_send (id, opts, type ) abort " opts = { id?, method?, result?, params?, on_notification }
214
217
let l: ctx = get (s: clients , a: id , {})
215
- if empty (l: ctx )
216
- return -1
217
- endif
218
+ if empty (l: ctx ) | return -1 | endif
218
219
219
220
let l: request = { ' jsonrpc' : ' 2.0' }
220
221
@@ -281,26 +282,156 @@ function! s:is_server_instantiated_notification(notification) abort
281
282
return ! has_key (a: notification , ' request' )
282
283
endfunction
283
284
285
+ function ! s: native_out_cb (cbctx, channel, response) abort
286
+ if ! has_key (a: cbctx , ' ctx' ) | return | endif
287
+ let l: ctx = a: cbctx [' ctx' ]
288
+ if has_key (a: response , ' method' ) && has_key (a: response , ' id' )
289
+ " it is a request from a server
290
+ let l: request = a: response
291
+ if has_key (l: ctx [' opts' ], ' on_request' )
292
+ call l: ctx [' opts' ][' on_request' ](l: ctx [' id' ], l: request )
293
+ endif
294
+ elseif ! has_key (a: response , ' id' ) && has_key (l: ctx [' opts' ], ' on_notification' )
295
+ " it is a notification
296
+ let l: on_notification_data = { ' response' : a: response }
297
+ try
298
+ call l: ctx [' opts' ][' on_notification' ](l: ctx [' id' ], l: on_notification_data , ' on_notification' )
299
+ catch
300
+ call lsp#log (' s:native_notification_callback on_notification() error' , v: exception , v: throwpoint )
301
+ endtry
302
+ endif
303
+ endfunction
304
+
305
+ function ! s: native_err_cb (cbctx, channel, response) abort
306
+ if ! has_key (a: cbctx , ' ctx' ) | return | endif
307
+ let l: ctx = a: cbctx [' ctx' ]
308
+ if has_key (l: ctx [' opts' ], ' on_stderr' )
309
+ try
310
+ call l: ctx [' opts' ][' on_stderr' ](l: ctx [' id' ], a: response , ' stderr' )
311
+ catch
312
+ call lsp#log (' s:on_stderr exception' , v: exception , v: throwpoint )
313
+ echom v: exception
314
+ endtry
315
+ endif
316
+ endfunction
317
+
284
318
" public apis {{{
285
319
286
320
function ! lsp#client#start (opts) abort
321
+ if g: lsp_use_native_client && lsp#utils#has_native_lsp_client ()
322
+ if has_key (a: opts , ' cmd' )
323
+ let l: cbctx = {}
324
+ let l: jobopt = { ' in_mode' : ' lsp' , ' out_mode' : ' lsp' , ' noblock' : 1 ,
325
+ \ ' out_cb' : function (' s:native_out_cb' , [l: cbctx ]),
326
+ \ ' err_cb' : function (' s:native_err_cb' , [l: cbctx ]),
327
+ \ }
328
+ if has_key (a: opts , ' cwd' ) | let l: jobopt [' cwd' ] = a: opts [' cwd' ] | endif
329
+ if has_key (a: opts , ' env' ) | let l: jobopt [' env' ] = a: opts [' env' ] | endif
330
+ let s: jobidseq += 1
331
+ let l: jobid = s: jobidseq " jobid == clientid
332
+ call lsp#log_verbose (' using native lsp client' )
333
+ let l: job = job_start (a: opts [' cmd' ], l: jobopt )
334
+ if job_status (l: job ) !=? ' run' | return -1 | endif
335
+ let l: ctx = s: create_context (l: jobid , a: opts )
336
+ let l: ctx [' id' ] = l: jobid
337
+ let l: ctx [' job' ] = l: job
338
+ let l: ctx [' channel' ] = job_getchannel (l: job )
339
+ let l: cbctx [' ctx' ] = l: ctx
340
+ return l: jobid
341
+ elseif has_key (a: opts , ' tcp' )
342
+ " add support for tcp
343
+ call lsp#log (' tcp not supported when using native lsp client' )
344
+ return -1
345
+ endif
346
+ endif
287
347
return s: lsp_start (a: opts )
288
348
endfunction
289
349
290
350
function ! lsp#client#stop (client_id) abort
291
- return s: lsp_stop (a: client_id )
351
+ if g: lsp_use_native_client && lsp#utils#has_native_lsp_client ()
352
+ let l: ctx = get (s: clients , a: client_id , {})
353
+ if empty (l: ctx ) | return | endif
354
+ call job_stop (l: ctx [' job' ])
355
+ else
356
+ return s: lsp_stop (a: client_id )
357
+ endif
292
358
endfunction
293
359
294
360
function ! lsp#client#send_request (client_id, opts) abort
295
- return s: lsp_send (a: client_id , a: opts , s: send_type_request )
361
+ if g: lsp_use_native_client && lsp#utils#has_native_lsp_client ()
362
+ let l: ctx = get (s: clients , a: client_id , {})
363
+ if empty (l: ctx ) | return -1 | endif
364
+ let l: request = {}
365
+ " id shouldn't be passed to request as vim will overwrite it. refer to :h language-server-protocol
366
+ if has_key (a: opts , ' method' ) | let l: request [' method' ] = a: opts [' method' ] | endif
367
+ if has_key (a: opts , ' params' ) | let l: request [' params' ] = a: opts [' params' ] | endif
368
+
369
+ call ch_sendexpr (l: ctx [' channel' ], l: request , { ' callback' : function (' s:on_response_native' , [l: ctx , l: request ]) })
370
+ let l: ctx [' requests' ][l: request [' id' ]] = l: request
371
+ if has_key (a: opts , ' on_notification' )
372
+ let l: ctx [' on_notifications' ][l: request [' id' ]] = a: opts [' on_notification' ]
373
+ endif
374
+ let l: ctx [' request_sequence' ] = l: request [' id' ]
375
+ return l: request [' id' ]
376
+ else
377
+ return s: lsp_send (a: client_id , a: opts , s: send_type_request )
378
+ endif
379
+ endfunction
380
+
381
+ function ! s: on_response_native (ctx, request, channel, response) abort
382
+ " request -> response
383
+ let l: on_notification_data = { ' response' : a: response , ' request' : a: request }
384
+ if has_key (a: ctx [' opts' ], ' on_notification' )
385
+ " call client's on_notification first
386
+ try
387
+ call a: ctx [' opts' ][' on_notification' ](a: ctx [' id' ], l: on_notification_data , ' on_notification' )
388
+ catch
389
+ call lsp#log (' s:on_response_native client option on_notification() error' , v: exception , v: throwpoint )
390
+ endtry
391
+ endif
392
+ if has_key (a: ctx [' on_notifications' ], a: request [' id' ])
393
+ " call lsp#client#send({ 'on_notification' }) second
394
+ try
395
+ call a: ctx [' on_notifications' ][a: request [' id' ]](a: ctx [' id' ], l: on_notification_data , ' on_notification' )
396
+ catch
397
+ call lsp#log (' s:on_response_native client request on_notification() error' , v: exception , v: throwpoint , a: request , a: response )
398
+ endtry
399
+ unlet a: ctx [' on_notifications' ][a: response [' id' ]]
400
+ if has_key (a: ctx [' requests' ], a: response [' id' ])
401
+ unlet a: ctx [' requests' ][a: response [' id' ]]
402
+ else
403
+ call lsp#log (' cannot find the request corresponding to response: ' , a: response )
404
+ endif
405
+ endif
296
406
endfunction
297
407
298
408
function ! lsp#client#send_notification (client_id, opts) abort
299
- return s: lsp_send (a: client_id , a: opts , s: send_type_notification )
409
+ if g: lsp_use_native_client && lsp#utils#has_native_lsp_client ()
410
+ let l: ctx = get (s: clients , a: client_id , {})
411
+ if empty (l: ctx ) | return -1 | endif
412
+ let l: request = {}
413
+ if has_key (a: opts , ' method' ) | let l: request [' method' ] = a: opts [' method' ] | endif
414
+ if has_key (a: opts , ' params' ) | let l: request [' params' ] = a: opts [' params' ] | endif
415
+ call ch_sendexpr (l: ctx [' channel' ], l: request )
416
+ return 0
417
+ else
418
+ return s: lsp_send (a: client_id , a: opts , s: send_type_notification )
419
+ endif
300
420
endfunction
301
421
302
422
function ! lsp#client#send_response (client_id, opts) abort
303
- return s: lsp_send (a: client_id , a: opts , s: send_type_response )
423
+ if g: lsp_use_native_client && lsp#utils#has_native_lsp_client ()
424
+ let l: ctx = get (s: clients , a: client_id , {})
425
+ if empty (l: ctx ) | return -1 | endif
426
+ let l: request = {}
427
+ if has_key (a: opts , ' id' ) | let l: request [' id' ] = a: opts [' id' ] | endif
428
+ if has_key (a: opts , ' result' ) | let l: request [' result' ] = a: opts [' result' ] | endif
429
+ if has_key (a: opts , ' error' ) | let l: request [' error' ] = a: opts [' error' ] | endif
430
+ call ch_sendexpr (l: ctx [' channel' ], l: request )
431
+ return 0
432
+ else
433
+ return s: lsp_send (a: client_id , a: opts , s: send_type_response )
434
+ endif
304
435
endfunction
305
436
306
437
function ! lsp#client#get_last_request_id (client_id) abort
0 commit comments