Skip to content

Commit

Permalink
feat: hack around LSPs returning filtered items
Browse files Browse the repository at this point in the history
  • Loading branch information
Saghen committed Aug 29, 2024
1 parent d6bad7b commit b58a382
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 11 deletions.
4 changes: 3 additions & 1 deletion lua/blink/cmp/sources/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ function sources.completions(context)
-- fixme: what if we refetch due to incomplete items or a trigger_character? the context trigger id wouldnt change
-- change so stale data would be returned if the source doesn't support cancellation
local cursor_column = vim.api.nvim_win_get_cursor(0)[2]
source.completions({ trigger = trigger_context }, function(items)
local source_context = vim.fn.deepcopy(context)
source_context.trigger = trigger_context
source.completions(source_context, function(items)
-- a new call was made or this one was cancelled
if sources.in_flight_id[source_name] ~= in_flight_id then return end
sources.in_flight_id[source_name] = -1
Expand Down
36 changes: 32 additions & 4 deletions lua/blink/cmp/sources/lsp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ function lsp.get_clients_with_capability(capability, filter)
end

function lsp.completions(context, callback)
-- todo: offset encoding is global but should be per-client
-- todo: should make separate LSP requests to return results earlier, in the case of slow LSPs
-- todo: should make a new call if the cursor moves backwards, before the first character of the trigger

-- no providers with completion support
if not lsp.has_capability('completionProvider') then return callback({ isIncomplete = false, items = {} }) end

Expand All @@ -52,6 +56,29 @@ function lsp.completions(context, callback)
params.context.triggerCharacter = context.trigger.character
end

-- special case, the first character of the context is a trigger character, so we adjust the position
-- sent to the LSP server to be the start of the trigger character
--
-- some LSP do their own filtering before returning results, which we want to avoid
-- since we perform fuzzy matching ourselves.
--
-- this also avoids having to make multiple calls to the LSP server in case characters are deleted
-- for these special cases
-- i.e. hello.wor| would be sent as hello.|wor
-- todo: should we still make two calls to the LSP server and merge?
local trigger_characters = lsp.get_trigger_characters()
local trigger_character_block_list = { ' ', '\n', '\t' }
local bounds = context.bounds
local trigger_character_before_context = bounds.line:sub(bounds.start_col - 1, bounds.start_col - 1)
if
vim.tbl_contains(trigger_characters, trigger_character_before_context)
and not vim.tbl_contains(trigger_character_block_list, trigger_character_before_context)
then
local offset_encoding = vim.lsp.get_clients({ bufnr = 0 })[1].offset_encoding
params.position.character =
vim.lsp.util.character_offset(0, params.position.line, bounds.start_col - 1, offset_encoding)
end

-- request from each of the clients
-- todo: refactor
lsp.cancel_completions_func = vim.lsp.buf_request_all(0, 'textDocument/completion', params, function(result)
Expand All @@ -75,6 +102,7 @@ function lsp.completions(context, callback)
for client_id, response in pairs(responses) do
for _, item in ipairs(response.items) do
-- todo: terraform lsp doesn't return a .kind in situations like `toset`, is there a default value we need to grab?
-- it doesn't seem to return itemDefaults either
item.kind = item.kind or vim.lsp.protocol.CompletionItemKind.Text
item.client_id = client_id

Expand All @@ -85,7 +113,7 @@ function lsp.completions(context, callback)
end

-- combine responses
-- todo: would be nice to pass multiple responses to the sources
-- todo: ideally pass multiple responses to the sources
-- so that we can do fine-grained isIncomplete
local combined_response = { isIncomplete = false, items = {} }
for _, response in pairs(responses) do
Expand All @@ -111,9 +139,9 @@ function lsp.resolve(item, callback)
return
end

local _, request_id = client.request('completionItem/resolve', item, function(error, result)
if error or result == nil then callback(item) end
callback(result)
local _, request_id = client.request('completionItem/resolve', item, function(error, resolved_item)
if error or resolved_item == nil then callback(item) end
callback(resolved_item)
end)
if request_id ~= nil then return function() client.cancel_request(request_id) end end
end
Expand Down
4 changes: 2 additions & 2 deletions lua/blink/cmp/sources/types.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
--- @class TriggerContext
--- @class CompletionTriggerContext
--- @field kind number
--- @field character string
---
--- @class CompletionContext : ShowContext
--- @field trigger TriggerContext | nil
--- @field trigger CompletionTriggerContext | nil
---
--- @class CompletionResponse
--- @field isIncomplete boolean
Expand Down
9 changes: 5 additions & 4 deletions lua/blink/cmp/trigger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
-- This can be used downstream to determine if we should make new requests to the sources or not.

--- @class TriggerBounds
--- @field line number
--- @field line string
--- @field line_number number
--- @field start_col number
--- @field end_col number
---
Expand Down Expand Up @@ -108,7 +109,7 @@ function trigger.show(opts)
opts = opts or {}

-- update context (to update bounds and treesitter node)
-- todo: this beahvior isn't obvious
-- todo: this behavior isn't obvious
trigger.context = trigger.get_context()

trigger.event_targets.on_show({
Expand Down Expand Up @@ -149,7 +150,7 @@ function trigger.within_query_bounds(cursor)

local row, col = cursor[1], cursor[2]
local bounds = trigger.context.bounds
return row == bounds.line and col >= bounds.start_col and col <= bounds.end_col
return row == bounds.line_number and col >= bounds.start_col and col <= bounds.end_col
end

------ Helpers ------
Expand Down Expand Up @@ -185,7 +186,7 @@ function helpers.get_query(regex)
end_col = end_col + 1
end

return { line = cursor_line, start_col = start_col, end_col = end_col }
return { line = line, line_number = cursor_line, start_col = start_col, end_col = end_col }
end

--- @return TSNode | nil
Expand Down

0 comments on commit b58a382

Please sign in to comment.