diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 5cd1e4eec7..cb711859da 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -544,6 +544,15 @@ local function lsp_enable_callback(bufnr) return end + -- Stop any clients that no longer apply to this buffer. + local clients = lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) + for _, client in ipairs(clients) do + if not can_start(bufnr, client.name, lsp.config[client.name]) then + lsp.buf_detach_client(bufnr, client.id) + end + end + + -- Start any clients that apply to this buffer. for name in vim.spairs(lsp._enabled_configs) do local config = lsp.config[name] if config and can_start(bufnr, name, config) then diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index d766d18192..3a2804ccaf 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -6504,6 +6504,58 @@ describe('LSP', function() end) end) + it('starts correct LSP and stops incorrect LSP when filetype changes', function() + exec_lua(create_server_definition) + + local tmp1 = t.tmpname(true) + + exec_lua(function() + local server = _G._create_server({ + handlers = { + initialize = function(_, _, callback) + callback(nil, { capabilities = {} }) + end, + }, + }) + + vim.lsp.config('foo', { + cmd = server.cmd, + filetypes = { 'foo' }, + root_markers = { '.foorc' }, + }) + + vim.lsp.config('bar', { + cmd = server.cmd, + filetypes = { 'bar' }, + root_markers = { '.foorc' }, + }) + + vim.lsp.enable('foo') + vim.lsp.enable('bar') + + vim.cmd.edit(tmp1) + end) + + local count_clients = function() + return exec_lua(function() + local foos = vim.lsp.get_clients({ name = 'foo', bufnr = 0 }) + local bars = vim.lsp.get_clients({ name = 'bar', bufnr = 0 }) + return { #foos, 'foo', #bars, 'bar' } + end) + end + + -- No filetype on the buffer yet, so no LSPs. + eq({ 0, 'foo', 0, 'bar' }, count_clients()) + + -- Set the filetype to 'foo', confirm a LSP starts. + exec_lua([[vim.bo.filetype = 'foo']]) + eq({ 1, 'foo', 0, 'bar' }, count_clients()) + + -- Set the filetype to 'bar', confirm a new LSP starts, and the old one goes away. + exec_lua([[vim.bo.filetype = 'bar']]) + eq({ 0, 'foo', 1, 'bar' }, count_clients()) + end) + it('validates config on attach', function() local tmp1 = t.tmpname(true) exec_lua(function()