Shougo / ddc-source-lsp

lsp source for ddc.vim
Other
66 stars 20 forks source link

Deal with multi language servers #31

Closed delphinus closed 2 years ago

delphinus commented 2 years ago

The current build cannot deal with buffers that multi language servers attach. Once request_candidates() is called, Neovim calls get_candidates() multiple times, but the denops process can only receive the first response.

I am using both typescript-language-server and efm-langserver, that attach to one buffer with a *.ts file. efm-langserver responds with an empty result for textDocument/completion before typescript-language-server, so the denops process cannot receive any completion candidate.

debugging diff ```diff diff --git a/lua/ddc_nvim_lsp.lua b/lua/ddc_nvim_lsp.lua index 1a57108..1e35aeb 100644 --- a/lua/ddc_nvim_lsp.lua +++ b/lua/ddc_nvim_lsp.lua @@ -5,6 +5,11 @@ local get_candidates = function(id, _, arg1, arg2) -- https://github.com/neovim/neovim/pull/15504 local result = ((vim.fn.has('nvim-0.6') == 1 or vim.fn.has('nvim-0.5.1')) and type(arg1) == 'table' and arg1 or arg2) + local count = 0 + if result then + count = result.items and #result.items or #result + end + print(vim.inspect{name = 'get_candidates', id = id, count = count}) if not result or result == 0 then api.nvim_call_function('ddc#callback', {id, { result = {}, @@ -24,6 +29,7 @@ local get_candidates = function(id, _, arg1, arg2) end local request_candidates = function(arguments, id) + print(vim.inspect{name = 'request_candidates', id = id}) local method = 'textDocument/completion' local method_supported = false for _, client in pairs(vim.lsp.buf_get_clients(bufnr)) do ```

With this patch above, I have received these logs in a buffer attached by typescript-language-server and efm-langserver.

{
  id = "source/nvim-lsp/1",
  name = "request_candidates"
}
{
  count = 0,
  id = "source/nvim-lsp/1",
  name = "get_candidates"
}
{
  count = 234,
  id = "source/nvim-lsp/1",
  name = "get_candidates"
}

This means one time request_candidates(), then two times get_candidates(). The denops process has received only the former one (an empty result).

This PR solves this problem by using lsp.buf_request_all instead of lsp.buf_request. It waits for all responses from attached language servers. Ideally, it may be better that we use lsp.buf_request and refresh candidates each time a language server responses. How do you think?

Shougo commented 2 years ago

Merged.