mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	fix(lsp): check method is supported when range formatting (#21970)
`vim.lsp.buf.format()` silently did nothing if no servers supported `textDocument/rangeFormatting` when formatting with a range. Issue found by `@hwrd:matrix.org` in the Matrix chat.
This commit is contained in:
		@@ -197,19 +197,20 @@ function M.format(options)
 | 
			
		||||
    clients = vim.tbl_filter(options.filter, clients)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  clients = vim.tbl_filter(function(client)
 | 
			
		||||
    return client.supports_method('textDocument/formatting')
 | 
			
		||||
  end, clients)
 | 
			
		||||
 | 
			
		||||
  if #clients == 0 then
 | 
			
		||||
    vim.notify('[LSP] Format request failed, no matching language servers.')
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  local mode = api.nvim_get_mode().mode
 | 
			
		||||
  local range = options.range
 | 
			
		||||
  if not range and mode == 'v' or mode == 'V' then
 | 
			
		||||
    range = range_from_selection()
 | 
			
		||||
  end
 | 
			
		||||
  local method = range and 'textDocument/rangeFormatting' or 'textDocument/formatting'
 | 
			
		||||
 | 
			
		||||
  clients = vim.tbl_filter(function(client)
 | 
			
		||||
    return client.supports_method(method)
 | 
			
		||||
  end, clients)
 | 
			
		||||
 | 
			
		||||
  if #clients == 0 then
 | 
			
		||||
    vim.notify('[LSP] Format request failed, no matching language servers.')
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ---@private
 | 
			
		||||
  local function set_range(client, params)
 | 
			
		||||
@@ -221,7 +222,6 @@ function M.format(options)
 | 
			
		||||
    return params
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  local method = range and 'textDocument/rangeFormatting' or 'textDocument/formatting'
 | 
			
		||||
  if options.async then
 | 
			
		||||
    local do_format
 | 
			
		||||
    do_format = function(idx, client)
 | 
			
		||||
 
 | 
			
		||||
@@ -3432,6 +3432,38 @@ describe('LSP', function()
 | 
			
		||||
      }
 | 
			
		||||
      eq(expected_range, result[3].params.range)
 | 
			
		||||
    end)
 | 
			
		||||
    it('Aborts with notify if no clients support requested method', function()
 | 
			
		||||
      exec_lua(create_server_definition)
 | 
			
		||||
      exec_lua([[
 | 
			
		||||
        vim.notify = function(msg, _)
 | 
			
		||||
          notify_msg = msg
 | 
			
		||||
        end
 | 
			
		||||
      ]])
 | 
			
		||||
      local fail_msg = "[LSP] Format request failed, no matching language servers."
 | 
			
		||||
      local function check_notify(name, formatting, range_formatting)
 | 
			
		||||
        local timeout_msg = "[LSP][" .. name .. "] timeout"
 | 
			
		||||
        exec_lua([[
 | 
			
		||||
          local formatting, range_formatting, name = ...
 | 
			
		||||
          local server = _create_server({ capabilities = {
 | 
			
		||||
            documentFormattingProvider = formatting,
 | 
			
		||||
            documentRangeFormattingProvider = range_formatting,
 | 
			
		||||
          }})
 | 
			
		||||
          vim.lsp.start({ name = name, cmd = server.cmd })
 | 
			
		||||
          notify_msg = nil
 | 
			
		||||
          vim.lsp.buf.format({ name = name, timeout_ms = 1 })
 | 
			
		||||
        ]], formatting, range_formatting, name)
 | 
			
		||||
        eq(formatting and timeout_msg or fail_msg, exec_lua('return notify_msg'))
 | 
			
		||||
        exec_lua([[
 | 
			
		||||
          notify_msg = nil
 | 
			
		||||
          vim.lsp.buf.format({ name = name, timeout_ms = 1, range = {start={1, 0}, ['end']={1, 0}}})
 | 
			
		||||
        ]])
 | 
			
		||||
        eq(range_formatting and timeout_msg or fail_msg, exec_lua('return notify_msg'))
 | 
			
		||||
      end
 | 
			
		||||
      check_notify("none", false, false)
 | 
			
		||||
      check_notify("formatting", true, false)
 | 
			
		||||
      check_notify("rangeFormatting", false, true)
 | 
			
		||||
      check_notify("both", true, true)
 | 
			
		||||
    end)
 | 
			
		||||
  end)
 | 
			
		||||
  describe('cmd', function()
 | 
			
		||||
    it('can connect to lsp server via rpc.connect', function()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user