fix(lsp.completion): add logging for request failures

This commit is contained in:
2026-04-19 00:41:05 +02:00
parent b4721bb444
commit b23fbb3704
3 changed files with 101 additions and 74 deletions
+32 -14
View File
@@ -1,5 +1,6 @@
local Item = require("lsp.completion.item") local Item = require("lsp.completion.item")
local Popup = require("lsp.completion.popup") local Popup = require("lsp.completion.popup")
local log = require("log")
local session = require("lsp.completion.session") local session = require("lsp.completion.session")
local GROUP = vim.api.nvim_create_augroup("ow.lsp.completion", { clear = true }) local GROUP = vim.api.nvim_create_augroup("ow.lsp.completion", { clear = true })
@@ -113,6 +114,7 @@ function M.setup()
return return
end end
---@param target ow.lsp.completion.Item
local function apply(target) local function apply(target)
local raw = target.raw local raw = target.raw
if raw.additionalTextEdits then if raw.additionalTextEdits then
@@ -123,10 +125,22 @@ function M.setup()
) )
end end
if raw.command then if raw.command then
client:request("workspace/executeCommand", { local method =
vim.lsp.protocol.Methods.workspace_executeCommand
client:request(method, {
command = raw.command.command, command = raw.command.command,
arguments = raw.command.arguments, arguments = raw.command.arguments,
}, nil, ev.buf) }, function(err)
if err then
log.warning(
"client %d: %s failed for %s: %s",
client.id,
method,
raw.command.title,
err.message
)
end
end, ev.buf)
end end
if target.snippet then if target.snippet then
local word = completed.word or "" local word = completed.word or ""
@@ -157,18 +171,22 @@ function M.setup()
and not item.raw.additionalTextEdits and not item.raw.additionalTextEdits
and not item.raw.command and not item.raw.command
then then
client:request( local method = vim.lsp.protocol.Methods.completionItem_resolve
vim.lsp.protocol.Methods.completionItem_resolve, client:request(method, item.raw, function(err, resolved)
item.raw, if err then
function(err, resolved) log.warning(
if err or not resolved then "client %d: %s failed: %s",
return client.id,
end method,
item:apply_resolved(resolved) err.message
apply(item) )
end, end
ev.buf if err or not resolved then
) return
end
item:apply_resolved(resolved)
apply(item)
end, ev.buf)
else else
apply(item) apply(item)
end end
+23 -18
View File
@@ -1,3 +1,4 @@
local log = require("log")
local MAX_WIDTH = 80 local MAX_WIDTH = 80
local MAX_HEIGHT = 20 local MAX_HEIGHT = 20
local HALF_HEIGHT = math.floor(MAX_HEIGHT / 2) local HALF_HEIGHT = math.floor(MAX_HEIGHT / 2)
@@ -114,24 +115,28 @@ end
function Popup:dispatch_resolve(client, item, ft, pum, word, buf) function Popup:dispatch_resolve(client, item, ft, pum, word, buf)
self:cancel_pending() self:cancel_pending()
self.resolved = nil self.resolved = nil
local _, request_id = client:request( local method = vim.lsp.protocol.Methods.completionItem_resolve
vim.lsp.protocol.Methods.completionItem_resolve, local _, request_id = client:request(method, item.raw, function(err, result)
item.raw, if err then
function(err, result) log.warning(
self.pending = nil "client %d: %s failed: %s",
if err or not result then client.id,
return method,
end err.message
local cur = vim.fn.complete_info({ "completed" }) )
if (vim.tbl_get(cur, "completed", "word") or "") ~= word then end
return self.pending = nil
end if err or not result then
item:apply_resolved(result) return
self.resolved = { word = word, item = item } end
self:show(item, ft, pum) local cur = vim.fn.complete_info({ "completed" })
end, if (vim.tbl_get(cur, "completed", "word") or "") ~= word then
buf return
) end
item:apply_resolved(result)
self.resolved = { word = word, item = item }
self:show(item, ft, pum)
end, buf)
if request_id then if request_id then
self.pending = { client = client, id = request_id } self.pending = { client = client, id = request_id }
end end
+46 -42
View File
@@ -3,6 +3,7 @@
local Item = require("lsp.completion.item") local Item = require("lsp.completion.item")
local kind = require("lsp.kind") local kind = require("lsp.kind")
local log = require("log")
local util = require("util") local util = require("util")
local REQUEST_DEBOUNCE_MS = 50 local REQUEST_DEBOUNCE_MS = 50
@@ -198,53 +199,56 @@ function Session:dispatch(trigger_kind, trigger_char, manual)
triggerKind = trigger_kind, triggerKind = trigger_kind,
triggerCharacter = trigger_char, triggerCharacter = trigger_char,
} }
self.cancel = vim.lsp.buf_request_all( local method = vim.lsp.protocol.Methods.textDocument_completion
buf, self.cancel = vim.lsp.buf_request_all(buf, method, params, function(result)
vim.lsp.protocol.Methods.textDocument_completion, if self.generation ~= gen then
params, return
function(result) end
vim.schedule(function()
-- Re-check: another dispatch may have fired between response
-- and the scheduled callback running.
if self.generation ~= gen then if self.generation ~= gen then
return return
end end
vim.schedule(function() if vim.fn.mode() ~= "i" then
-- Re-check: another dispatch may have fired between response return
-- and the scheduled callback running. end
if self.generation ~= gen then local word_start, cursor = word_bounds()
return if
not self.manual
and not self.trigger_char
and word_start == cursor
then
return
end
self.is_incomplete = false
for client_id, response in pairs(result) do
if response.err then
log.warning(
"client %d: %s failed: %s",
client_id,
method,
response.err.message
)
end end
if vim.fn.mode() ~= "i" then local r = response.result
return if type(r) == "table" and r.isIncomplete then
self.is_incomplete = true
break
end end
local word_start, cursor = word_bounds() end
if local start = word_start
not self.manual for _, response in pairs(result) do
and not self.trigger_char local pos = edit_start(response)
and word_start == cursor if pos then
then start = pos.character
return break
end end
self.is_incomplete = false end
for _, response in pairs(result) do local base = vim.api.nvim_get_current_line():sub(start + 1, cursor)
local r = response.result vim.fn.complete(start + 1, build_items(result, base))
if type(r) == "table" and r.isIncomplete then end)
self.is_incomplete = true end)
break
end
end
local start = word_start
for _, response in pairs(result) do
local pos = edit_start(response)
if pos then
start = pos.character
break
end
end
local base =
vim.api.nvim_get_current_line():sub(start + 1, cursor)
vim.fn.complete(start + 1, build_items(result, base))
end)
end
)
end end
local session = Session.new() local session = Session.new()
@@ -284,7 +288,7 @@ function M.on_insert_char_pre()
local kind_num = is_trigger local kind_num = is_trigger
and vim.lsp.protocol.CompletionTriggerKind.TriggerCharacter and vim.lsp.protocol.CompletionTriggerKind.TriggerCharacter
or vim.lsp.protocol.CompletionTriggerKind.Invoked or vim.lsp.protocol.CompletionTriggerKind.Invoked
dispatcher:call(nil, kind_num, is_trigger and char or nil) dispatcher(kind_num, is_trigger and char or nil)
end end
return M return M