]> Sergey Matveev's repositories - vim-lsp.git/blob - autoload/lsp/capabilities.vim
Add basic support for InsertReplaceEdit in completion reply. Fixes #354
[vim-lsp.git] / autoload / lsp / capabilities.vim
1 vim9script
2
3 # Functions for managing the LSP server and client capabilities
4
5 import './options.vim' as opt
6
7 # Process the server capabilities
8 #   interface ServerCapabilities
9 export def ProcessServerCaps(lspserver: dict<any>, caps: dict<any>)
10   var serverEncoding = 'utf-16'
11   if lspserver.caps->has_key('positionEncoding')
12     serverEncoding = lspserver.caps.positionEncoding
13   elseif lspserver.caps->has_key('~additionalInitResult_offsetEncoding')
14     serverEncoding = lspserver.caps['~additionalInitResult_offsetEncoding']
15   endif
16
17   if lspserver.forceOffsetEncoding != ''
18     serverEncoding = lspserver.forceOffsetEncoding
19   endif
20
21   # one of 'utf-8', 'utf-16' or 'utf-32'
22   if serverEncoding == 'utf-8'
23     lspserver.posEncoding = 8
24   elseif serverEncoding == 'utf-16'
25     lspserver.posEncoding = 16
26   else
27     lspserver.posEncoding = 32
28   endif
29
30   if has('patch-9.0.1629') && lspserver.posEncoding != 32
31     lspserver.needOffsetEncoding = true
32   else
33     lspserver.needOffsetEncoding = false
34   endif
35
36   # completionProvider
37   if lspserver.caps->has_key('completionProvider')
38     lspserver.isCompletionProvider = true
39     if lspserver.caps.completionProvider->has_key('resolveProvider')
40       lspserver.isCompletionResolveProvider =
41                         lspserver.caps.completionProvider.resolveProvider
42     else
43       lspserver.isCompletionResolveProvider = false
44     endif
45   else
46     lspserver.isCompletionProvider = false
47     lspserver.isCompletionResolveProvider = false
48   endif
49
50   # definitionProvider
51   if lspserver.caps->has_key('definitionProvider')
52     if lspserver.caps.definitionProvider->type() == v:t_bool
53       lspserver.isDefinitionProvider = lspserver.caps.definitionProvider
54     else
55       lspserver.isDefinitionProvider = true
56     endif
57   else
58     lspserver.isDefinitionProvider = false
59   endif
60
61   # declarationProvider
62   if lspserver.caps->has_key('declarationProvider')
63     if lspserver.caps.declarationProvider->type() == v:t_bool
64       lspserver.isDeclarationProvider = lspserver.caps.declarationProvider
65     else
66       lspserver.isDeclarationProvider = true
67     endif
68   else
69     lspserver.isDeclarationProvider = false
70   endif
71
72   # typeDefinitionProvider
73   if lspserver.caps->has_key('typeDefinitionProvider')
74     if lspserver.caps.typeDefinitionProvider->type() == v:t_bool
75       lspserver.isTypeDefinitionProvider = lspserver.caps.typeDefinitionProvider
76     else
77       lspserver.isTypeDefinitionProvider = true
78     endif
79   else
80     lspserver.isTypeDefinitionProvider = false
81   endif
82
83   # implementationProvider
84   if lspserver.caps->has_key('implementationProvider')
85     if lspserver.caps.implementationProvider->type() == v:t_bool
86       lspserver.isImplementationProvider = lspserver.caps.implementationProvider
87     else
88       lspserver.isImplementationProvider = true
89     endif
90   else
91     lspserver.isImplementationProvider = false
92   endif
93
94   # signatureHelpProvider
95   if lspserver.caps->has_key('signatureHelpProvider')
96     lspserver.isSignatureHelpProvider = true
97   else
98     lspserver.isSignatureHelpProvider = false
99   endif
100
101   # hoverProvider
102   if lspserver.caps->has_key('hoverProvider')
103     if lspserver.caps.hoverProvider->type() == v:t_bool
104       lspserver.isHoverProvider = lspserver.caps.hoverProvider
105     else
106       lspserver.isHoverProvider = true
107     endif
108   else
109     lspserver.isHoverProvider = false
110   endif
111
112   # referencesProvider
113   if lspserver.caps->has_key('referencesProvider')
114     if lspserver.caps.referencesProvider->type() == v:t_bool
115       lspserver.isReferencesProvider = lspserver.caps.referencesProvider
116     else
117       lspserver.isReferencesProvider = true
118     endif
119   else
120     lspserver.isReferencesProvider = false
121   endif
122
123   # documentHighlightProvider
124   if lspserver.caps->has_key('documentHighlightProvider')
125     if lspserver.caps.documentHighlightProvider->type() == v:t_bool
126       lspserver.isDocumentHighlightProvider =
127                                 lspserver.caps.documentHighlightProvider
128     else
129       lspserver.isDocumentHighlightProvider = true
130     endif
131   else
132     lspserver.isDocumentHighlightProvider = false
133   endif
134
135   # documentSymbolProvider
136   if lspserver.caps->has_key('documentSymbolProvider')
137     if lspserver.caps.documentSymbolProvider->type() == v:t_bool
138       lspserver.isDocumentSymbolProvider =
139                                 lspserver.caps.documentSymbolProvider
140     else
141       lspserver.isDocumentSymbolProvider = true
142     endif
143   else
144     lspserver.isDocumentSymbolProvider = false
145   endif
146
147   # documentFormattingProvider
148   if lspserver.caps->has_key('documentFormattingProvider')
149     if lspserver.caps.documentFormattingProvider->type() == v:t_bool
150       lspserver.isDocumentFormattingProvider =
151                                 lspserver.caps.documentFormattingProvider
152     else
153       lspserver.isDocumentFormattingProvider = true
154     endif
155   else
156     lspserver.isDocumentFormattingProvider = false
157   endif
158
159   # callHierarchyProvider
160   if lspserver.caps->has_key('callHierarchyProvider')
161     if lspserver.caps.callHierarchyProvider->type() == v:t_bool
162       lspserver.isCallHierarchyProvider =
163                                 lspserver.caps.callHierarchyProvider
164     else
165       lspserver.isCallHierarchyProvider = true
166     endif
167   else
168     lspserver.isCallHierarchyProvider = false
169   endif
170
171   # typeHierarchyProvider
172   if lspserver.caps->has_key('typeHierarchyProvider')
173     lspserver.isTypeHierarchyProvider = true
174   else
175     lspserver.isTypeHierarchyProvider = false
176   endif
177
178   # renameProvider
179   if lspserver.caps->has_key('renameProvider')
180     if lspserver.caps.renameProvider->type() == v:t_bool
181       lspserver.isRenameProvider = lspserver.caps.renameProvider
182     else
183       lspserver.isRenameProvider = true
184     endif
185   else
186     lspserver.isRenameProvider = false
187   endif
188
189   # codeActionProvider
190   if lspserver.caps->has_key('codeActionProvider')
191     if lspserver.caps.codeActionProvider->type() == v:t_bool
192       lspserver.isCodeActionProvider = lspserver.caps.codeActionProvider
193     else
194       lspserver.isCodeActionProvider = true
195     endif
196   else
197     lspserver.isCodeActionProvider = false
198   endif
199
200   # codeLensProvider
201   if lspserver.caps->has_key('codeLensProvider')
202     lspserver.isCodeLensProvider = true
203     if lspserver.caps.codeLensProvider->has_key('resolveProvider')
204       lspserver.isCodeLensResolveProvider = true
205     else
206       lspserver.isCodeLensResolveProvider = false
207     endif
208   else
209     lspserver.isCodeLensProvider = false
210   endif
211
212   # workspaceSymbolProvider
213   if lspserver.caps->has_key('workspaceSymbolProvider')
214     if lspserver.caps.workspaceSymbolProvider->type() == v:t_bool
215       lspserver.isWorkspaceSymbolProvider =
216                                 lspserver.caps.workspaceSymbolProvider
217     else
218       lspserver.isWorkspaceSymbolProvider = true
219     endif
220   else
221     lspserver.isWorkspaceSymbolProvider = false
222   endif
223
224   # selectionRangeProvider
225   if lspserver.caps->has_key('selectionRangeProvider')
226     if lspserver.caps.selectionRangeProvider->type() == v:t_bool
227       lspserver.isSelectionRangeProvider =
228                                 lspserver.caps.selectionRangeProvider
229     else
230       lspserver.isSelectionRangeProvider = true
231     endif
232   else
233     lspserver.isSelectionRangeProvider = false
234   endif
235
236   # foldingRangeProvider
237   if lspserver.caps->has_key('foldingRangeProvider')
238     if lspserver.caps.foldingRangeProvider->type() == v:t_bool
239       lspserver.isFoldingRangeProvider = lspserver.caps.foldingRangeProvider
240     else
241       lspserver.isFoldingRangeProvider = true
242     endif
243   else
244     lspserver.isFoldingRangeProvider = false
245   endif
246
247   # inlayHintProvider
248   if lspserver.caps->has_key('inlayHintProvider')
249     if lspserver.caps.inlayHintProvider->type() == v:t_bool
250       lspserver.isInlayHintProvider = lspserver.caps.inlayHintProvider
251     else
252       lspserver.isInlayHintProvider = true
253     endif
254   else
255     lspserver.isInlayHintProvider = false
256   endif
257
258   # clangdInlayHintsProvider
259   if lspserver.caps->has_key('clangdInlayHintsProvider')
260     lspserver.isClangdInlayHintsProvider =
261                                         lspserver.caps.clangdInlayHintsProvider
262   else
263     lspserver.isClangdInlayHintsProvider = false
264   endif
265
266   # textDocumentSync capabilities
267   lspserver.supportsDidSave = false
268   # Default to TextDocumentSyncKind.None
269   lspserver.textDocumentSync = 0
270   if lspserver.caps->has_key('textDocumentSync')
271     if lspserver.caps.textDocumentSync->type() == v:t_bool
272         || lspserver.caps.textDocumentSync->type() == v:t_number
273       lspserver.supportsDidSave = lspserver.caps.textDocumentSync
274       lspserver.textDocumentSync = lspserver.caps.textDocumentSync
275     elseif lspserver.caps.textDocumentSync->type() == v:t_dict
276       # "save"
277       if lspserver.caps.textDocumentSync->has_key('save')
278         if lspserver.caps.textDocumentSync.save->type() == v:t_bool
279             || lspserver.caps.textDocumentSync.save->type() == v:t_number
280           lspserver.supportsDidSave = lspserver.caps.textDocumentSync.save
281         elseif lspserver.caps.textDocumentSync.save->type() == v:t_dict
282           lspserver.supportsDidSave = true
283         endif
284       endif
285       # "change"
286       if lspserver.caps.textDocumentSync->has_key('change')
287         lspserver.textDocumentSync = lspserver.caps.textDocumentSync.change
288       endif
289     endif
290   endif
291 enddef
292
293 # Return all the LSP client capabilities
294 export def GetClientCaps(): dict<any>
295   # client capabilities (ClientCapabilities)
296   var clientCaps: dict<any> = {
297     workspace: {
298       workspaceFolders: true,
299       applyEdit: true,
300       configuration: true
301     },
302     textDocument: {
303       callHierarchy: {
304         dynamicRegistration: false
305       },
306       codeAction: {
307         dynamicRegistration: false,
308         codeActionLiteralSupport: {
309           codeActionKind: {
310             valueSet: ['', 'quickfix', 'refactor', 'refactor.extract',
311                         'refactor.inline', 'refactor.rewrite', 'source',
312                         'source.organizeImports']
313           }
314         },
315         isPreferredSupport: true,
316         disabledSupport: true
317       },
318       codeLens: {
319         dynamicRegistration: false
320       },
321       completion: {
322         dynamicRegistration: false,
323         completionItem: {
324           documentationFormat: ['markdown', 'plaintext'],
325           resolveSupport: {properties: ['detail', 'documentation']},
326           snippetSupport: opt.lspOptions.snippetSupport,
327           insertReplaceSupport: false
328         },
329         completionItemKind: {valueSet: range(1, 25)}
330       },
331       documentSymbol: {
332         dynamicRegistration: false,
333         hierarchicalDocumentSymbolSupport: true,
334         symbolKind: {valueSet: range(1, 25)}
335       },
336       hover: {
337         contentFormat: ['markdown', 'plaintext']
338       },
339       foldingRange: {lineFoldingOnly: true},
340       inlayHint: {dynamicRegistration: false},
341       synchronization: {
342         didSave: true
343       },
344       declaration: {linkSupport: true},
345       definition: {linkSupport: true},
346       typeDefinition: {linkSupport: true},
347       implementation: {linkSupport: true},
348       signatureHelp: {
349         signatureInformation: {
350           documentationFormat: ['markdown', 'plaintext'],
351           activeParameterSupport: true
352         }
353       }
354     },
355     window: {},
356     general: {
357       # Currently we always send character count as position offset,
358       # which meanas only utf-32 is supported.
359       # Adding utf-16 simply for good mesure, as I'm scared some servers will
360       # give up if they don't support utf-32 only.
361       positionEncodings: ['utf-32', 'utf-16']
362     },
363     # This is the way clangd expects to be informated about supported encodings:
364     # https://clangd.llvm.org/extensions#utf-8-offsets
365     offsetEncoding: ['utf-32', 'utf-16']
366   }
367
368   # Vim patch 1629 is needed to properly encode/decode UTF-16 offsets
369   if has('patch-9.0.1629')
370     clientCaps.general.positionEncodings = ['utf-32', 'utf-16', 'utf-8']
371     clientCaps.offsetEncoding = ['utf-32', 'utf-16', 'utf-8']
372   endif
373
374   return clientCaps
375 enddef
376
377 # vim: tabstop=8 shiftwidth=2 softtabstop=2