mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	fix(lsp): schedule call to vim.lsp.start for async root_dir (#31998)
When `root_dir` is a function it can (and often will) call the provided callback function in a fast API context (e.g. in the `on_exit` handler of `vim.system`). When the callback function is executed we should ensure that it runs vim.lsp.start on the main event loop.
This commit is contained in:
		@@ -513,7 +513,9 @@ local function lsp_enable_callback(bufnr)
 | 
			
		||||
        ---@param root_dir string
 | 
			
		||||
        config.root_dir(function(root_dir)
 | 
			
		||||
          config.root_dir = root_dir
 | 
			
		||||
          start(config)
 | 
			
		||||
          vim.schedule(function()
 | 
			
		||||
            start(config)
 | 
			
		||||
          end)
 | 
			
		||||
        end)
 | 
			
		||||
      else
 | 
			
		||||
        start(config)
 | 
			
		||||
 
 | 
			
		||||
@@ -6259,37 +6259,42 @@ describe('LSP', function()
 | 
			
		||||
      )
 | 
			
		||||
    end)
 | 
			
		||||
 | 
			
		||||
    it('supports a function for root_dir', function()
 | 
			
		||||
    it('supports async function for root_dir', function()
 | 
			
		||||
      exec_lua(create_server_definition)
 | 
			
		||||
 | 
			
		||||
      local tmp1 = t.tmpname(true)
 | 
			
		||||
 | 
			
		||||
      eq(
 | 
			
		||||
        'some_dir',
 | 
			
		||||
        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_dir = function(cb)
 | 
			
		||||
              cb('some_dir')
 | 
			
		||||
      exec_lua(function()
 | 
			
		||||
        local server = _G._create_server({
 | 
			
		||||
          handlers = {
 | 
			
		||||
            initialize = function(_, _, callback)
 | 
			
		||||
              callback(nil, { capabilities = {} })
 | 
			
		||||
            end,
 | 
			
		||||
          })
 | 
			
		||||
          vim.lsp.enable('foo')
 | 
			
		||||
          },
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
          vim.cmd.edit(assert(tmp1))
 | 
			
		||||
          vim.bo.filetype = 'foo'
 | 
			
		||||
        vim.lsp.config('foo', {
 | 
			
		||||
          cmd = server.cmd,
 | 
			
		||||
          filetypes = { 'foo' },
 | 
			
		||||
          root_dir = function(cb)
 | 
			
		||||
            vim.system({ 'sleep', '0' }, {}, function()
 | 
			
		||||
              cb('some_dir')
 | 
			
		||||
            end)
 | 
			
		||||
          end,
 | 
			
		||||
        })
 | 
			
		||||
        vim.lsp.enable('foo')
 | 
			
		||||
 | 
			
		||||
          return vim.lsp.get_clients({ bufnr = vim.api.nvim_get_current_buf() })[1].root_dir
 | 
			
		||||
        end)
 | 
			
		||||
      )
 | 
			
		||||
        vim.cmd.edit(assert(tmp1))
 | 
			
		||||
        vim.bo.filetype = 'foo'
 | 
			
		||||
      end)
 | 
			
		||||
 | 
			
		||||
      retry(nil, 1000, function()
 | 
			
		||||
        eq(
 | 
			
		||||
          'some_dir',
 | 
			
		||||
          exec_lua(function()
 | 
			
		||||
            return vim.lsp.get_clients({ bufnr = vim.api.nvim_get_current_buf() })[1].root_dir
 | 
			
		||||
          end)
 | 
			
		||||
        )
 | 
			
		||||
      end)
 | 
			
		||||
    end)
 | 
			
		||||
  end)
 | 
			
		||||
end)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user