Neovim lsp auto-fix / fix-current?

Viewed 1469

I was looking for a solution similar to CoC's coc-fix-current but using native lsp for Neovim 0.5 but I did not find such thing in the documentation, is there any way to achieve this through other method?

3 Answers

I had this problem and by hacking up the code that the telescope.nvim plugin uses to list and run code actions, came up with this monstrosity:

local function run_action(action, offse)
    if action.edit or type(action.command) == "table" then
        if action.edit then
            vim.lsp.util.apply_workspace_edit(action.edit, offse)
        end
        if type(action.command) == "table" then
            vim.lsp.buf.execute_command(action.command)
        end
    else
        vim.lsp.buf.execute_command(action)
    end
end

local function do_action(action, client)
    if
      not action.edit
      and client
      and type(client.resolved_capabilities.code_action) == "table"
      and client.resolved_capabilities.code_action.resolveProvider
    then
        client.request("codeAction/resolve", action, function(err, real)
            if err then
                return
            end
            if real then
                run_action(real, client.offset_encoding)
            else
                run_action(action, client.offset_encoding)
            end
        end)
    else
        run_action(action, client.offset_encoding) 
    end
end

return function() 
    local params = vim.lsp.util.make_range_params() -- get params for current position
    params.context = {
        diagnostics = vim.lsp.diagnostic.get_line_diagnostics(),
        only = {"quickfix"}
    }

    local results, err = vim.lsp.buf_request_sync(
        0, -- current buffer
        "textDocument/codeAction", -- get code actions
        params,
        900
    )

    if err then return end

    if not results or vim.tbl_isempty(results) then
        print "No quickfixes!"
        return
    end

    -- we have an action!
    for cid, resp in pairs(results) do
        if resp.result then
            for _, result in pairs(resp.result) do 
                -- this is the first action, run it
                do_action(result, vim.lsp.get_client_by_id(cid))
                return
            end
        end 
    end

    print "No quickfixes!"
end

Since it's lua, you'll need to place it in a .lua file somewhere that nvim searches for modules (for example, as ~/.config/nvim/lua/lsp_fixcurrent.lua) and then bind to :lua require("lsp_fixcurrent")()

Maybe you are looking for: vim.lsp.buf.code_action()?

mincrmatt12 answer, updated for newer neovim (0.8?) which complains client.resolved_capabilities should not be used.

local function run_action(action, offse)
    if action.edit or type(action.command) == "table" then
        if action.edit then
            vim.lsp.util.apply_workspace_edit(action.edit, offse)
        end
        if type(action.command) == "table" then
            vim.lsp.buf.execute_command(action.command)
        end
    else
        vim.lsp.buf.execute_command(action)
    end
end

local function do_action(action, client)
    if
        not action.edit
        and client
        and type(client.server_capabilities) == "table"
        and client.server_capabilities.resolveProvider
    then
        client.request("codeAction/resolve", action, function(err, real)
            if err then
                return
            end
            if real then
                run_action(real, client.offset_encoding)
            else
                run_action(action, client.offset_encoding)
            end
        end)
    else
        run_action(action, client.offset_encoding)
    end
end

return function()
    local params = vim.lsp.util.make_range_params() -- get params for current position
    params.context = {
        diagnostics = vim.lsp.diagnostic.get_line_diagnostics(),
        only = { "quickfix" },
    }

    local results, err = vim.lsp.buf_request_sync(
        0, -- current buffer
        "textDocument/codeAction", -- get code actions
        params,
        900
    )

    if err then
        return
    end

    if not results or vim.tbl_isempty(results) then
        print("No quickfixes!")
        return
    end

    -- we have an action!
    for cid, resp in pairs(results) do
        if resp.result then
            for _, result in pairs(resp.result) do
                -- this is the first action, run it
                do_action(result, vim.lsp.get_client_by_id(cid))
                return
            end
        end
    end

    print("No quickfixes!")
end
Related