Vey
Vey

Reputation: 475

How to send errors from Neovim LSP to ALE

ALE has an API for sending errors to it from other sources. I'm using this like shown below and it works for the first error. More specifically, if I make one edit that results in an LSP error, the error will be displayed by ALE in the location list. If I make any further keystrokes, the location list is emptied again.

I can also trigger this behavior if I disable LSP, load ALE, manually call ShowResults and then press any other key in insert mode.

My hypothesis is that ALEs linting in insert mode (per default) kicks in. If LSP is disabled and there are no linters registered for the current file type, it doesn't find any errors (obviously, there's nothing that could report any) and so it empties my location list again. So the steps are: open buffer without LSP, call ShowResults, location list opens, press i, press any key, location list is empty

Now I thought that it was because I wasn't implementing the full ALE API. So I added a hook (2nd snippet). I can verify that this hook is called and that it generates valid messages. If I keep the location list open I can even see all the expected errors flickering across the loclist. I can navigate to those errors with :lolder, but I don't know why ALE always adds another, empty location list, after the LSP is done doing its job.

Or maybe I'm doing something wrong here.

vim.lsp.handlers["textDocument/publishDiagnostics"] = function(_, _, params, client_id, _, config)
  local uri = params.uri
  local bufnr = vim.uri_to_bufnr(uri)
  if not bufnr then
    return
  end

  local diagnostics = params.diagnostics
  if not diagnostics or vim.tbl_isempty(diagnostics) then
    vim.fn['ale#other_source#ShowResults'](bufnr, "nvim-lsp", {})
    return
  end

  -- Important so we can pull diagnostics from this table when ALE asks for
  -- them
  vim.lsp.diagnostic.save(diagnostics, bufnr, client_id)

  local messages = {}

  for _, event in ipairs(diagnostics) do
    -- :h ale-localist-format
    local msg = {}
    msg.text = event.message
    msg.lnum = event.range.start.line
    msg.end_lnum = event.range["end"].line
    msg.col = event.range.start.character
    msg.end_col = event.range["end"].character
    msg.bufnr = bufnr
    msg.nr = event.severity
    table.insert(messages, msg)
  end

  vim.fn['ale#other_source#ShowResults'](bufnr, "nvim-lsp", messages)
end

Second snippet which is called from the 'on_attach' function of the Neovim LSP

  function ALEHook(bufnr)
      vim.fn['ale#other_source#StartChecking'](bufnr, "nvim-lsp")
      local diagnostics = vim.lsp.diagnostic.get(bufnr, client.id)
      if not diagnostics or vim.tbl_isempty(diagnostics) then
        vim.fn['ale#other_source#ShowResults'](bufnr, "nvim-lsp", {})
        return
      end

      local messages = {}

      for _, event in ipairs(diagnostics) do
        local msg = {}
        msg.text = event.message
        msg.lnum = event.range.start.line
        msg.end_lnum = event.range["end"].line
        msg.col = event.range.start.character
        msg.end_col = event.range["end"].character
        msg.bufnr = bufnr
        msg.nr = event.severity
        table.insert(messages, msg)
      end

      vim.fn['ale#other_source#ShowResults'](bufnr, "nvim-lsp", messages)
    end

    api.nvim_command('augroup ALEHookLSP')
    api.nvim_command('autocmd!')
    api.nvim_command('autocmd User ALEWantResults call v:lua.ALEHook(g:ale_want_results_buffer)')
    api.nvim_command('augroup END')

Upvotes: 1

Views: 641

Answers (0)

Related Questions