refactor(codelens): split into modules and add cancellation
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
local Row = require("lsp.codelens.row")
|
||||
local log = require("log")
|
||||
|
||||
---@class ow.lsp.codelens.RefreshTask
|
||||
---@field session ow.lsp.codelens.Session
|
||||
---@field aborted boolean
|
||||
---@field private cancels fun()[]
|
||||
local RefreshTask = {}
|
||||
RefreshTask.__index = RefreshTask
|
||||
|
||||
---@param session ow.lsp.codelens.Session
|
||||
---@return ow.lsp.codelens.RefreshTask
|
||||
function RefreshTask.new(session)
|
||||
return setmetatable({
|
||||
session = session,
|
||||
aborted = false,
|
||||
cancels = {},
|
||||
}, RefreshTask)
|
||||
end
|
||||
|
||||
---@param cancel fun()
|
||||
function RefreshTask:track(cancel)
|
||||
table.insert(self.cancels, cancel)
|
||||
end
|
||||
|
||||
function RefreshTask:abort()
|
||||
self.aborted = true
|
||||
for _, cancel in ipairs(self.cancels) do
|
||||
pcall(cancel)
|
||||
end
|
||||
self.cancels = {}
|
||||
end
|
||||
|
||||
---@param client vim.lsp.Client
|
||||
---@param lens lsp.CodeLens
|
||||
---@param row ow.lsp.codelens.Row
|
||||
function RefreshTask:resolve(client, lens, row)
|
||||
local method = vim.lsp.protocol.Methods.codeLens_resolve
|
||||
local _, req_id = client:request(
|
||||
method,
|
||||
lens,
|
||||
---@param resolved lsp.CodeLens?
|
||||
function(err, resolved)
|
||||
if self.aborted then
|
||||
return
|
||||
end
|
||||
if err then
|
||||
log.warning(
|
||||
"client %d: %s failed: %s",
|
||||
client.id,
|
||||
method,
|
||||
err.message
|
||||
)
|
||||
end
|
||||
row:resolve(resolved)
|
||||
row:render(self.session.buf)
|
||||
end,
|
||||
self.session.buf
|
||||
)
|
||||
if req_id then
|
||||
self:track(function()
|
||||
client:cancel_request(req_id)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
---@param rows table<integer, ow.lsp.codelens.Row>
|
||||
---@param client vim.lsp.Client?
|
||||
---@param lens lsp.CodeLens
|
||||
function RefreshTask:process_lens(rows, client, lens)
|
||||
local row = rows[lens.range.start.line]
|
||||
if not row then
|
||||
row = Row.new(lens.range.start.line)
|
||||
rows[lens.range.start.line] = row
|
||||
end
|
||||
if lens.command then
|
||||
row:add(lens)
|
||||
return
|
||||
end
|
||||
if
|
||||
not client
|
||||
or not client:supports_method(vim.lsp.protocol.Methods.codeLens_resolve)
|
||||
then
|
||||
return
|
||||
end
|
||||
row:expect()
|
||||
self:resolve(client, lens, row)
|
||||
end
|
||||
|
||||
---@param responses table<integer, ow.lsp.CodeLensResponse>
|
||||
function RefreshTask:process_responses(responses)
|
||||
local method = vim.lsp.protocol.Methods.textDocument_codeLens
|
||||
local session = self.session
|
||||
local new_rows = {}
|
||||
for client_id, response in pairs(responses) do
|
||||
if response.err then
|
||||
log.warning(
|
||||
"client %d: %s failed: %s",
|
||||
client_id,
|
||||
method,
|
||||
response.err.message
|
||||
)
|
||||
end
|
||||
if not response.err and type(response.result) == "table" then
|
||||
local client = vim.lsp.get_client_by_id(client_id)
|
||||
for _, lens in ipairs(response.result) do
|
||||
self:process_lens(new_rows, client, lens)
|
||||
end
|
||||
end
|
||||
end
|
||||
session.rows = new_rows
|
||||
session:render()
|
||||
end
|
||||
|
||||
function RefreshTask:run()
|
||||
local method = vim.lsp.protocol.Methods.textDocument_codeLens
|
||||
local params = {
|
||||
textDocument = vim.lsp.util.make_text_document_params(self.session.buf),
|
||||
}
|
||||
local cancel = vim.lsp.buf_request_all(
|
||||
self.session.buf,
|
||||
method,
|
||||
params,
|
||||
function(responses)
|
||||
if self.aborted then
|
||||
return
|
||||
end
|
||||
self:process_responses(responses)
|
||||
end
|
||||
)
|
||||
self:track(cancel)
|
||||
end
|
||||
|
||||
return RefreshTask
|
||||
Reference in New Issue
Block a user