CodeAction doesn't work realiably when using multiple servers
I use clangd and cspell-lsp at once. Here is an example configuration for cspell for testing purposes.
let cspell =
\ #{name: 'cspell',
\ filetype: [
\ 'c',
\ 'cpp',
\ 'json',
\ 'gitcommit',
\ 'json',
\ 'markdown',
\ 'python',
\ 'vim',
\ 'yaml',
\ ],
\ path: 'cspell-lsp',
\ args: ['--stdio',
\ '--sortWords',
\ '--config', '/home/jan/.vim/cSpell.json',
\ ]
\ }
cspell-lsp code actions are not always offered to me. There seems to be a race condition here about which server starts first. If I put cspell-lsp as the first server to load, it works, but then clangd code actions don't work anymore.
Can you provide some sample code and the expected code actions to reproduce this issue?
Sure, here is an example C program and an LSP configuration to easily swap the orders of the servers.
The cspell-lsp can be installed with npm install -g @vlabo/cspell-lsp. Only the code actions of the first server work. I have to admit that the cspell-lsp also has some issues. Sometimes code actions are only shown when you are at the end of the line (see this issue).
/* ssdasdasdadjakdaslkdasldjaskd */
int main(int argc, char *argv[])
{
int mybksdjaskdaksdalablvar = 1
return 0;
}
let lspOpts = #{
\ aleSupport: v:false,
\ autoComplete: v:true,
\ autoHighlight: v:true,
\ autoHighlightDiags: v:true,
\ autoPopulateDiags: v:true,
\ completionMatcher: 'case',
\ completionMatcherValue: 1,
\ diagSignErrorText: '❗',
\ diagSignHintText: '💡',
\ diagSignInfoText: '💡',
\ diagSignWarningText: '💡',
\ diagSignPriority: {
\ 'Error': 100,
\ 'Warning': 99,
\ 'Information': 98,
\ 'Hint': 97
\ },
\ echoSignature: v:false,
\ hideDisabledCodeActions: v:false,
\ highlightDiagInline: v:true,
\ hoverInPreview: v:false,
\ ignoreMissingServer: v:true,
\ keepFocusInDiags: v:true,
\ keepFocusInReferences: v:true,
\ completionTextEdit: v:true,
\ diagVirtualTextAlign: 'above',
\ noNewlineInCompletion: v:false,
\ popupBorder: v:true,
\ popupBorderSignatureHelp: v:true,
\ omniComplete: v:null,
\ outlineOnRight: v:true,
\ outlineWinSize: 50,
\ semanticHighlight: v:true,
\ showDiagInBalloon: v:false,
\ showDiagInPopup: v:true,
\ showDiagOnStatusLine: v:false,
\ showDiagWithSign: v:true,
\ showDiagWithVirtualText: v:false,
\ showInlayHints: v:false,
\ showSignature: v:true,
\ snippetSupport: v:true,
\ ultisnipsSupport: v:true,
\ useBufferCompletion: v:true,
\ usePopupInCodeAction: v:true,
\ vsnipSupport: v:false,
\ useQuickfixForLocations: v:false,
\ bufferCompletionTimeout: 1,
\ customCompletionKinds: v:false,
\ completionKinds: {},
\ filterCompletionDuplicates: v:true,
\ }
autocmd User LspSetup call LspOptionsSet(lspOpts)
let clangd =
\ #{name: 'clangd',
\ filetype: ['c', 'cpp'],
\ path: 'clangd',
\ args: [
\ '--background-index',
\ '--clang-tidy',
\ '--completion-style=detailed'
\ ]
\ }
let cspell =
\ #{name: 'cspell',
\ filetype: ['c', 'cpp'],
\ path: 'cspell-lsp',
\ args: ['--stdio',
\ '--sortWords',
\ '--config', '/home/jan/.vim/cSpell.json',
\ ]
\ }
" Enable language servers
let lspServers = []
" cspell-lsp first -> only cspell code actions work.
" I you swap the two language servers, only clangd code actions work
call add(lspServers, cspell)
call add(lspServers, clangd)
autocmd VimEnter * call LspAddServer(lspServers)
nnoremap <leader>ac :LspCodeAction<CR>
nnoremap <silent> <leader>pe :LspDiagPrev<CR>
nnoremap <silent> <leader>ne :LspDiagNext<CR>
So I just tried another spellchecking language server and it doesn't start up with clangd at all. There definitely seem to still be problems with using two language servers at the same time. I add codebook before clangd, codebook works and clangd doesn't. If I add clangd first, codebooks doesn't work. Probably a race condition somewhere.
Here is the config
let codebook =
\ #{name: 'codebook',
\ filetype: [
\ 'c',
\ 'cpp',
\ 'json',
\ 'vim',
\ 'css',
\ 'gitcommit',
\ 'go',
\ 'html',
\ 'js',
\ 'json',
\ 'julia',
\ 'markdown',
\ 'matlab',
\ 'pkl',
\ 'python',
\ 'rust',
\ 'ts',
\ 'vim',
\ 'yaml',
\ ],
\ path: 'codebook-lsp',
\ args: ['serve'
\ ],
\ root_markers: [ '.git', 'codebook.toml', '.codebook.toml' ],
\ }
I played around with it a little more. The codebook server suffers from the exact same issues as the cspell-lsp, which can't be. This is an issue with the client.
Is it actually possible to register the same capability for multiple servers or can everything (hover, diagnostics, code actions etc.) only be registered once per buffer?