@@ -40,6 +40,10 @@ function lsp.get_clients_with_capability(capability, filter)
40
40
end
41
41
42
42
function lsp .completions (context , callback )
43
+ -- todo: offset encoding is global but should be per-client
44
+ -- todo: should make separate LSP requests to return results earlier, in the case of slow LSPs
45
+ -- todo: should make a new call if the cursor moves backwards, before the first character of the trigger
46
+
43
47
-- no providers with completion support
44
48
if not lsp .has_capability (' completionProvider' ) then return callback ({ isIncomplete = false , items = {} }) end
45
49
@@ -52,6 +56,29 @@ function lsp.completions(context, callback)
52
56
params .context .triggerCharacter = context .trigger .character
53
57
end
54
58
59
+ -- special case, the first character of the context is a trigger character, so we adjust the position
60
+ -- sent to the LSP server to be the start of the trigger character
61
+ --
62
+ -- some LSP do their own filtering before returning results, which we want to avoid
63
+ -- since we perform fuzzy matching ourselves.
64
+ --
65
+ -- this also avoids having to make multiple calls to the LSP server in case characters are deleted
66
+ -- for these special cases
67
+ -- i.e. hello.wor| would be sent as hello.|wor
68
+ -- todo: should we still make two calls to the LSP server and merge?
69
+ local trigger_characters = lsp .get_trigger_characters ()
70
+ local trigger_character_block_list = { ' ' , ' \n ' , ' \t ' }
71
+ local bounds = context .bounds
72
+ local trigger_character_before_context = bounds .line :sub (bounds .start_col - 1 , bounds .start_col - 1 )
73
+ if
74
+ vim .tbl_contains (trigger_characters , trigger_character_before_context )
75
+ and not vim .tbl_contains (trigger_character_block_list , trigger_character_before_context )
76
+ then
77
+ local offset_encoding = vim .lsp .get_clients ({ bufnr = 0 })[1 ].offset_encoding
78
+ params .position .character =
79
+ vim .lsp .util .character_offset (0 , params .position .line , bounds .start_col - 1 , offset_encoding )
80
+ end
81
+
55
82
-- request from each of the clients
56
83
-- todo: refactor
57
84
lsp .cancel_completions_func = vim .lsp .buf_request_all (0 , ' textDocument/completion' , params , function (result )
@@ -75,6 +102,7 @@ function lsp.completions(context, callback)
75
102
for client_id , response in pairs (responses ) do
76
103
for _ , item in ipairs (response .items ) do
77
104
-- todo: terraform lsp doesn't return a .kind in situations like `toset`, is there a default value we need to grab?
105
+ -- it doesn't seem to return itemDefaults either
78
106
item .kind = item .kind or vim .lsp .protocol .CompletionItemKind .Text
79
107
item .client_id = client_id
80
108
@@ -85,7 +113,7 @@ function lsp.completions(context, callback)
85
113
end
86
114
87
115
-- combine responses
88
- -- todo: would be nice to pass multiple responses to the sources
116
+ -- todo: ideally pass multiple responses to the sources
89
117
-- so that we can do fine-grained isIncomplete
90
118
local combined_response = { isIncomplete = false , items = {} }
91
119
for _ , response in pairs (responses ) do
@@ -111,9 +139,9 @@ function lsp.resolve(item, callback)
111
139
return
112
140
end
113
141
114
- local _ , request_id = client .request (' completionItem/resolve' , item , function (error , result )
115
- if error or result == nil then callback (item ) end
116
- callback (result )
142
+ local _ , request_id = client .request (' completionItem/resolve' , item , function (error , resolved_item )
143
+ if error or resolved_item == nil then callback (item ) end
144
+ callback (resolved_item )
117
145
end )
118
146
if request_id ~= nil then return function () client .cancel_request (request_id ) end end
119
147
end
0 commit comments