mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	fix(lsp): reuse client if configs match and no root dir
Problem:
An LSP configuration that creates client with no root_dir or
workspace_folders can result in vim.lsp.enable attaching to it multiple
times.
Solution:
When checking existing clients, reuse a client if it wasn't initially
configured have any workspace_folders. This more closely matches the
behaviour we had prior to d9235ef
			
			
This commit is contained in:
		 Lewis Russell
					Lewis Russell
				
			
				
					committed by
					
						 Lewis Russell
						Lewis Russell
					
				
			
			
				
	
			
			
			 Lewis Russell
						Lewis Russell
					
				
			
						parent
						
							7940ec6913
						
					
				
				
					commit
					9c20342297
				
			| @@ -201,23 +201,28 @@ local function reuse_client_default(client, config) | ||||
|   end | ||||
|  | ||||
|   local config_folders = lsp._get_workspace_folders(config.workspace_folders or config.root_dir) | ||||
|     or {} | ||||
|   local config_folders_included = 0 | ||||
|  | ||||
|   if not next(config_folders) then | ||||
|     return false | ||||
|   if not config_folders or not next(config_folders) then | ||||
|     -- Reuse if the client was configured with no workspace folders | ||||
|     local client_config_folders = | ||||
|       lsp._get_workspace_folders(client.config.workspace_folders or client.config.root_dir) | ||||
|     return not client_config_folders or not next(client_config_folders) | ||||
|   end | ||||
|  | ||||
|   for _, config_folder in ipairs(config_folders) do | ||||
|     local found = false | ||||
|     for _, client_folder in ipairs(client.workspace_folders) do | ||||
|       if config_folder.uri == client_folder.uri then | ||||
|         config_folders_included = config_folders_included + 1 | ||||
|         found = true | ||||
|         break | ||||
|       end | ||||
|     end | ||||
|     if not found then | ||||
|       return false | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   return config_folders_included == #config_folders | ||||
|   return true | ||||
| end | ||||
|  | ||||
| --- Reset defaults set by `set_defaults`. | ||||
|   | ||||
| @@ -731,9 +731,10 @@ describe('vim.lsp.completion: item conversion', function() | ||||
|   ) | ||||
| end) | ||||
|  | ||||
| --- @param name string | ||||
| --- @param completion_result lsp.CompletionList | ||||
| --- @return integer | ||||
| local function create_server(completion_result) | ||||
| local function create_server(name, completion_result) | ||||
|   return exec_lua(function() | ||||
|     local server = _G._create_server({ | ||||
|       capabilities = { | ||||
| @@ -751,7 +752,7 @@ local function create_server(completion_result) | ||||
|     local bufnr = vim.api.nvim_get_current_buf() | ||||
|     vim.api.nvim_win_set_buf(0, bufnr) | ||||
|     return vim.lsp.start({ | ||||
|       name = 'dummy', | ||||
|       name = name, | ||||
|       cmd = server.cmd, | ||||
|       on_attach = function(client, bufnr0) | ||||
|         vim.lsp.completion.enable(true, client.id, bufnr0, { | ||||
| @@ -800,7 +801,7 @@ describe('vim.lsp.completion: protocol', function() | ||||
|   end | ||||
|  | ||||
|   it('fetches completions and shows them using complete on trigger', function() | ||||
|     create_server({ | ||||
|     create_server('dummy', { | ||||
|       isIncomplete = false, | ||||
|       items = { | ||||
|         { | ||||
| @@ -892,7 +893,7 @@ describe('vim.lsp.completion: protocol', function() | ||||
|   end) | ||||
|  | ||||
|   it('merges results from multiple clients', function() | ||||
|     create_server({ | ||||
|     create_server('dummy1', { | ||||
|       isIncomplete = false, | ||||
|       items = { | ||||
|         { | ||||
| @@ -900,7 +901,7 @@ describe('vim.lsp.completion: protocol', function() | ||||
|         }, | ||||
|       }, | ||||
|     }) | ||||
|     create_server({ | ||||
|     create_server('dummy2', { | ||||
|       isIncomplete = false, | ||||
|       items = { | ||||
|         { | ||||
| @@ -933,7 +934,7 @@ describe('vim.lsp.completion: protocol', function() | ||||
|         }, | ||||
|       }, | ||||
|     } | ||||
|     local client_id = create_server(completion_list) | ||||
|     local client_id = create_server('dummy', completion_list) | ||||
|  | ||||
|     exec_lua(function() | ||||
|       _G.called = false | ||||
| @@ -970,7 +971,7 @@ describe('vim.lsp.completion: protocol', function() | ||||
|   end) | ||||
|  | ||||
|   it('enable(…,{convert=fn}) custom word/abbr format', function() | ||||
|     create_server({ | ||||
|     create_server('dummy', { | ||||
|       isIncomplete = false, | ||||
|       items = { | ||||
|         { | ||||
| @@ -1012,7 +1013,7 @@ describe('vim.lsp.completion: integration', function() | ||||
|     exec_lua(function() | ||||
|       vim.o.completeopt = 'menuone,noselect' | ||||
|     end) | ||||
|     create_server(completion_list) | ||||
|     create_server('dummy', completion_list) | ||||
|     feed('i world<esc>0ih<c-x><c-o>') | ||||
|     retry(nil, nil, function() | ||||
|       eq( | ||||
|   | ||||
| @@ -5184,8 +5184,8 @@ describe('LSP', function() | ||||
|         local win = vim.api.nvim_get_current_win() | ||||
|         vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'local x = 10', '', 'print(x)' }) | ||||
|         vim.api.nvim_win_set_cursor(win, { 3, 6 }) | ||||
|         local client_id1 = assert(vim.lsp.start({ name = 'dummy', cmd = server1.cmd })) | ||||
|         local client_id2 = assert(vim.lsp.start({ name = 'dummy', cmd = server2.cmd })) | ||||
|         local client_id1 = assert(vim.lsp.start({ name = 'dummy1', cmd = server1.cmd })) | ||||
|         local client_id2 = assert(vim.lsp.start({ name = 'dummy2', cmd = server2.cmd })) | ||||
|         local response | ||||
|         vim.lsp.buf.definition({ | ||||
|           on_list = function(r) | ||||
| @@ -6203,5 +6203,33 @@ describe('LSP', function() | ||||
|         end) | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('does not attach to buffers more than once if no root_dir', function() | ||||
|       exec_lua(create_server_definition) | ||||
|  | ||||
|       local tmp1 = t.tmpname(true) | ||||
|  | ||||
|       eq( | ||||
|         1, | ||||
|         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' } }) | ||||
|           vim.lsp.enable('foo') | ||||
|  | ||||
|           vim.cmd.edit(assert(tmp1)) | ||||
|           vim.bo.filetype = 'foo' | ||||
|           vim.bo.filetype = 'foo' | ||||
|  | ||||
|           return #vim.lsp.get_clients({ bufnr = vim.api.nvim_get_current_buf() }) | ||||
|         end) | ||||
|       ) | ||||
|     end) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user