Skip to content

Commit 3927128

Browse files
committed
feat: resolve item before accept
1 parent 18f0610 commit 3927128

File tree

3 files changed

+53
-68
lines changed

3 files changed

+53
-68
lines changed

lua/blink/cmp/accept/init.lua

+49-41
Original file line numberDiff line numberDiff line change
@@ -6,55 +6,63 @@ local brackets_lib = require('blink.cmp.accept.brackets')
66
local function accept(item)
77
require('blink.cmp.trigger.completion').hide()
88

9-
-- create an undo point
10-
if require('blink.cmp.config').accept.create_undo_point then
11-
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<C-g>u', true, true, true), 'n', true)
12-
end
9+
-- start the resolve immediately since text changes can invalidate the item
10+
-- with some LSPs (i.e. rust-analyzer) causing them to return the item as-is
11+
-- without i.e. auto-imports
12+
require('blink.cmp.sources.lib').resolve(item):map(function(resolved_item)
13+
local all_text_edits =
14+
vim.deepcopy(resolved_item and resolved_item.additionalTextEdits or item.additionalTextEdits or {})
1315

14-
item = vim.deepcopy(item)
15-
item.textEdit = text_edits_lib.get_from_item(item)
16+
-- create an undo point
17+
if require('blink.cmp.config').accept.create_undo_point then
18+
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<C-g>u', true, true, true), 'n', true)
19+
end
1620

17-
-- Add brackets to the text edit if needed
18-
local brackets_status, text_edit_with_brackets, offset = brackets_lib.add_brackets(vim.bo.filetype, item)
19-
item.textEdit = text_edit_with_brackets
21+
item = vim.deepcopy(item)
22+
item.textEdit = text_edits_lib.get_from_item(item)
2023

21-
-- Snippet
22-
if item.insertTextFormat == vim.lsp.protocol.InsertTextFormat.Snippet then
23-
-- We want to handle offset_encoding and the text edit api can do this for us
24-
-- so we empty the newText and apply
25-
local temp_text_edit = vim.deepcopy(item.textEdit)
26-
temp_text_edit.newText = ''
27-
text_edits_lib.apply_text_edits(item.client_id, { temp_text_edit })
24+
-- Add brackets to the text edit if needed
25+
local brackets_status, text_edit_with_brackets, offset = brackets_lib.add_brackets(vim.bo.filetype, item)
26+
item.textEdit = text_edit_with_brackets
2827

29-
-- Expand the snippet
30-
vim.snippet.expand(item.textEdit.newText)
28+
-- Snippet
29+
if item.insertTextFormat == vim.lsp.protocol.InsertTextFormat.Snippet then
30+
-- We want to handle offset_encoding and the text edit api can do this for us
31+
-- so we empty the newText and apply
32+
local temp_text_edit = vim.deepcopy(item.textEdit)
33+
temp_text_edit.newText = ''
34+
table.insert(all_text_edits, temp_text_edit)
35+
text_edits_lib.apply_text_edits(item.client_id, all_text_edits)
36+
37+
-- Expand the snippet
38+
vim.snippet.expand(item.textEdit.newText)
3139

3240
-- OR Normal: Apply the text edit and move the cursor
33-
else
34-
text_edits_lib.apply_text_edits(item.client_id, { item.textEdit })
35-
vim.api.nvim_win_set_cursor(0, {
36-
item.textEdit.range.start.line + 1,
37-
item.textEdit.range.start.character + #item.textEdit.newText + offset,
38-
})
39-
end
40-
41-
-- Check semantic tokens for brackets, if needed, and apply additional text edits
42-
if brackets_status == 'check_semantic_token' then
43-
-- todo: since we apply the additional text edits after, auto imported functions will not
44-
-- get auto brackets. If we apply them before, we have to modify the textEdit to compensate
45-
brackets_lib.add_brackets_via_semantic_token(vim.bo.filetype, item, function()
41+
else
42+
table.insert(all_text_edits, item.textEdit)
43+
text_edits_lib.apply_text_edits(item.client_id, all_text_edits)
44+
vim.api.nvim_win_set_cursor(0, {
45+
item.textEdit.range.start.line + 1,
46+
item.textEdit.range.start.character + #item.textEdit.newText + offset,
47+
})
48+
end
49+
50+
-- Check semantic tokens for brackets, if needed, and apply additional text edits
51+
if brackets_status == 'check_semantic_token' then
52+
-- todo: since we apply the additional text edits after, auto imported functions will not
53+
-- get auto brackets. If we apply them before, we have to modify the textEdit to compensate
54+
brackets_lib.add_brackets_via_semantic_token(vim.bo.filetype, item, function()
55+
require('blink.cmp.trigger.completion').show_if_on_trigger_character()
56+
require('blink.cmp.trigger.signature').show_if_on_trigger_character()
57+
end)
58+
else
4659
require('blink.cmp.trigger.completion').show_if_on_trigger_character()
4760
require('blink.cmp.trigger.signature').show_if_on_trigger_character()
48-
text_edits_lib.apply_additional_text_edits(item)
49-
end)
50-
else
51-
require('blink.cmp.trigger.completion').show_if_on_trigger_character()
52-
require('blink.cmp.trigger.signature').show_if_on_trigger_character()
53-
text_edits_lib.apply_additional_text_edits(item)
54-
end
55-
56-
-- Notify the rust module that the item was accessed
57-
require('blink.cmp.fuzzy').access(item)
61+
end
62+
63+
-- Notify the rust module that the item was accessed
64+
require('blink.cmp.fuzzy').access(item)
65+
end)
5866
end
5967

6068
return accept

lua/blink/cmp/accept/text-edits.lua

-16
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,6 @@ function text_edits.undo_text_edit(text_edit)
5555
vim.lsp.util.apply_text_edits({ text_edit }, vim.api.nvim_get_current_buf(), 'utf-16')
5656
end
5757

58-
--- @param item blink.cmp.CompletionItem
59-
function text_edits.apply_additional_text_edits(item)
60-
-- Apply additional text edits
61-
-- LSPs can either include these in the initial response or require a resolve
62-
-- These are used for things like auto-imports
63-
-- todo: if the main text edit was before this text edit, do we need to compensate?
64-
if item.additionalTextEdits ~= nil and next(item.additionalTextEdits) ~= nil then
65-
text_edits.apply_text_edits(item.client_id, item.additionalTextEdits)
66-
else
67-
require('blink.cmp.sources.lib').resolve(item, function(resolved_item)
68-
resolved_item = resolved_item or item
69-
text_edits.apply_text_edits(resolved_item.client_id, resolved_item.additionalTextEdits or {})
70-
end)
71-
end
72-
end
73-
7458
--- @param item blink.cmp.CompletionItem
7559
--- todo: doesnt work when the item contains characters not included in the context regex
7660
function text_edits.guess_text_edit(item)

lua/blink/cmp/sources/lib/init.lua

+4-11
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ local config = require('blink.cmp.config')
1515
--- @field cancel_completions fun()
1616
--- @field listen_on_completions fun(callback: fun(context: blink.cmp.Context, items: blink.cmp.CompletionItem[]))
1717
--- @field apply_max_items_for_completions fun(context: blink.cmp.Context, items: blink.cmp.CompletionItem[]): blink.cmp.CompletionItem[]
18-
--- @field resolve fun(item: blink.cmp.CompletionItem, callback: fun(resolved_item: lsp.CompletionItem | nil)): (fun(): nil) | nil
18+
--- @field resolve fun(item: blink.cmp.CompletionItem): blink.cmp.Task
1919
--- @field get_signature_help_trigger_characters fun(): { trigger_characters: string[], retrigger_characters: string[] }
2020
--- @field get_signature_help fun(context: blink.cmp.SignatureHelpContext, callback: fun(signature_help: lsp.SignatureHelp | nil)): (fun(): nil) | nil
2121
--- @field cancel_signature_help fun()
@@ -143,23 +143,17 @@ end
143143

144144
--- Resolve ---
145145

146-
function sources.resolve(item, callback)
146+
function sources.resolve(item)
147147
local item_source = nil
148148
for _, source in pairs(sources.providers) do
149149
if source.id == item.source_id then
150150
item_source = source
151151
break
152152
end
153153
end
154+
if item_source == nil then return async.task.new(function(resolve) resolve() end) end
154155

155-
if item_source == nil then
156-
callback(nil)
157-
return function() end
158-
end
159-
return item_source:resolve(item):map(function(resolved_item) callback(resolved_item) end):catch(function(err)
160-
vim.print('failed to resolve item with error: ' .. err)
161-
callback(nil)
162-
end)
156+
return item_source:resolve(item):catch(function(err) vim.print('failed to resolve item with error: ' .. err) end)
163157
end
164158

165159
--- Signature help ---
@@ -239,7 +233,6 @@ function sources.get_lsp_capabilities(override, include_nvim_defaults)
239233
'documentation',
240234
'detail',
241235
'additionalTextEdits',
242-
'textEdits',
243236
-- todo: support more properties? should test if it improves latency
244237
},
245238
},

0 commit comments

Comments
 (0)