Skip to content

LspHover cancels previous LSP server requests when using multiple LSP servers #1600

@zbinlin

Description

@zbinlin
["--->",1,"ls-typescript",{"method":"textDocument/hover","on_notification":"---funcref---","params":{"textDocument":{"uri":"..."},"position":{"character":31,"line":6}}}]
["--->",1,"ls-typescript",{"method":"$/cancelRequest","params":{"id":4}}]
["--->",2,"ls-tailwindcss",{"method":"textDocument/hover","on_notification":"---funcref---","params":{"textDocument":{"uri":"..."},"position":{"character":31,"line":6}}}]
["<---",1,"ls-typescript",{"response":{"id":4,"jsonrpc":"2.0","result":null},"request":{"method":"textDocument/hover","jsonrpc":"2.0","id":4,"params":{"textDocument":{"uri":"..."},"position":{"character":31,"line":6}}}}]
["<---",2,"ls-tailwindcss",{"response":{"id":2,"jsonrpc":"2.0","result":null},"request":{"method":"textDocument/hover","jsonrpc":"2.0","id":2,"params":{"textDocument":{"uri":"..."},"position":{"character":31,"line":6}}}}]

It seems the issue is caused by the flatMap operator: when the next source subscribes, it cancels previous source.

call lsp#callbag#pipe(
\ lsp#callbag#fromList(l:servers),
\ lsp#callbag#flatMap({server->
\ lsp#request(server, l:request)
\ }),
\ lsp#callbag#tap({x->s:show_hover(l:ui, x['server_name'], x['request'], x['response'])}),
\ lsp#callbag#takeUntil(lsp#callbag#pipe(
\ lsp#stream(),
\ lsp#callbag#filter({x->has_key(x, 'command')}),
\ )),
\ lsp#callbag#subscribe(),
\ )

Here is a minimal reproducible example using callbag.vim:

function s:source(ctx, next, error, complete) abort
	call timer_start(500, {->a:next(a:ctx['value'])})
	call timer_start(1000, {->a:complete()})
	return function('s:cleanup', [a:ctx])
endfunction

function s:create(v) abort
	let l:ctx = {
	\ 'value': a:v,
	\}
	return callbag#create(function('s:source', [l:ctx]))
endfunction

function s:cleanup(ctx) abort
	call s:log('clear: ' .. a:ctx['value'])
endfunction

function s:log(message) abort
	echom a:message
endfunction

call callbag#pipe(
	\ callbag#fromList(['foo', 'bar']),
	\ callbag#flatMap({x->s:create(x)}),
	\ callbag#tap({x->s:log('value: ' .. x)}),
	\ callbag#subscribe({
	\  'next': {x->s:log('value received')},
	\  'error': {e->s:log(e)},
	\  'complete': {->s:log('complete')},
	\}),
	\)

Expected output:

value: foo
value received
value: bar
value received
complete

Actual output:

clear: foo
value: bar
value received
complete

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions