]> git.madduck.net Git - etc/vim.git/blob - .vim/bundle/ale/test/lsp/test_lsp_startup.vader

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Merge commit 'd49e95aa7ba744f0a7f544aca43afdb6aab41f24' as '.vim/bundle/asyncomplete...
[etc/vim.git] / .vim / bundle / ale / test / lsp / test_lsp_startup.vader
1 Before:
2   Save g:ale_run_synchronously
3
4   let g:ale_run_synchronously = 1
5   unlet! g:ale_run_synchronously_callbacks
6   unlet! g:ale_run_synchronously_emulate_commands
7
8   runtime autoload/ale/lsp.vim
9   runtime autoload/ale/lsp_linter.vim
10   runtime autoload/ale/engine.vim
11   runtime autoload/ale/job.vim
12   runtime autoload/ale/socket.vim
13
14   let g:job_map = {}
15   let g:emulate_job_failure = 0
16   let g:next_job_id = 1
17   let g:lsp_started = 0
18
19   let g:socket_map = {}
20   let g:emulate_socket_failure = 0
21   let g:next_channel_id = 0
22
23   let g:message_buffer = ''
24   let g:calls = []
25
26   function! ale#engine#IsExecutable(buffer, executable) abort
27     return !empty(a:executable)
28   endfunction
29
30   function! ale#job#HasOpenChannel(job_id) abort
31     return has_key(g:job_map, a:job_id)
32   endfunction
33
34   function! ale#job#Stop(job_id) abort
35     if has_key(g:job_map, a:job_id)
36       call remove(g:job_map, a:job_id)
37     endif
38   endfunction
39
40   function! ale#job#Start(command, options) abort
41     if g:emulate_job_failure
42       return 0
43     endif
44
45     let l:job_id = g:next_job_id
46     let g:next_job_id += 1
47     let g:job_map[l:job_id] = [a:command, a:options]
48
49     return l:job_id
50   endfunction
51
52   function! ale#job#SendRaw(job_id, data) abort
53     let g:message_buffer .= a:data
54   endfunction
55
56   function! ale#socket#IsOpen(channel_id) abort
57     return has_key(g:socket_map, a:channel_id)
58   endfunction
59
60   function! ale#socket#Close(channel_id) abort
61     if has_key(g:socket_map, a:channel_id)
62       call remove(g:socket_map, a:channel_id)
63     endif
64   endfunction
65
66   function! ale#socket#Open(address, options) abort
67     if g:emulate_socket_failure
68       return -1
69     endif
70
71     let l:channel_id = g:next_channel_id
72     let g:next_channel_id += 1
73     let g:socket_map[l:channel_id] = [a:address, a:options]
74
75     return l:channel_id
76   endfunction
77
78   function! ale#socket#Send(channel_id, data) abort
79     let g:message_buffer .= a:data
80   endfunction
81
82   function! PopMessages() abort
83     let l:message_list = []
84
85     for l:line in split(g:message_buffer, '\(\r\|\n\|Content-Length\)\+')
86       if l:line[:0] is '{'
87         let l:data = json_decode(l:line)
88
89         call add(l:message_list, l:data)
90       endif
91     endfor
92
93     let g:message_buffer = ''
94
95     return l:message_list
96   endfunction
97
98   function! SendMessage(message) abort
99     let l:conn_id = keys(ale#lsp#GetConnections())[0]
100     let l:body = json_encode(a:message)
101     let l:data = 'Content-Length: ' . strlen(l:body) . "\r\n\r\n" . l:body
102
103     call ale#lsp#HandleMessage(l:conn_id, l:data)
104   endfunction
105
106   function! Start(buffer) abort
107     let l:linter = values(ale#linter#GetLintersLoaded())[0][0]
108
109     return ale#lsp_linter#StartLSP(
110     \ a:buffer,
111     \ l:linter,
112     \ {linter, details -> add(g:calls, [linter.name, details])},
113     \)
114   endfunction
115
116   function! AssertInitSuccess(linter_name, conn_prefix, language, root, command, buffer) abort
117     let l:messages = PopMessages()
118
119     if a:linter_name is# 'tsserver'
120       AssertEqual
121       \ [
122       \   {
123       \     'seq': v:null,
124       \     'arguments': {
125       \       'file': expand('#' . a:buffer . ':p'),
126       \     },
127       \     'type': 'request',
128       \     'command': 'open',
129       \   },
130       \ ],
131       \ l:messages
132     else
133       AssertEqual
134       \ [
135       \   {
136       \     'method': 'initialize',
137       \     'jsonrpc': '2.0',
138       \     'id': 1,
139       \     'params': {
140       \       'initializationOptions': {},
141       \       'rootUri': ale#path#ToFileURI(a:root),
142       \       'rootPath': a:root,
143       \       'processId': getpid(),
144       \       'capabilities': {
145       \         'workspace': {
146       \           'applyEdit': v:false,
147       \           'didChangeConfiguration': {
148       \             'dynamicRegistration': v:false,
149       \           },
150       \           'symbol': {
151       \             'dynamicRegistration': v:false,
152       \           },
153       \           'workspaceFolders': v:false,
154       \           'configuration': v:false,
155       \         },
156       \         'textDocument': {
157       \           'synchronization': {
158       \             'dynamicRegistration': v:false,
159       \             'willSave': v:false,
160       \             'willSaveWaitUntil': v:false,
161       \             'didSave': v:true,
162       \           },
163       \           'completion': {
164       \             'dynamicRegistration': v:false,
165       \             'completionItem': {
166       \               'snippetSupport': v:false,
167       \               'commitCharactersSupport': v:false,
168       \               'documentationFormat': ['plaintext', 'markdown'],
169       \               'deprecatedSupport': v:false,
170       \               'preselectSupport': v:false,
171       \             },
172       \             'contextSupport': v:false,
173       \           },
174       \           'hover': {
175       \             'dynamicRegistration': v:false,
176       \             'contentFormat': ['plaintext', 'markdown'],
177       \           },
178       \           'references': {
179       \             'dynamicRegistration': v:false,
180       \           },
181       \           'documentSymbol': {
182       \             'dynamicRegistration': v:false,
183       \             'hierarchicalDocumentSymbolSupport': v:false,
184       \           },
185       \           'definition': {
186       \             'dynamicRegistration': v:false,
187       \             'linkSupport': v:false,
188       \           },
189       \           'typeDefinition': {
190       \             'dynamicRegistration': v:false,
191       \           },
192       \           'implementation': {
193       \             'dynamicRegistration': v:false,
194       \             'linkSupport': v:false,
195       \           },
196       \           'diagnostic': {
197       \             'dynamicRegistration': v:true,
198       \             'relatedDocumentSupport': v:true,
199       \           },
200       \           'publishDiagnostics': {
201       \             'relatedInformation': v:true,
202       \           },
203       \           'codeAction': {
204       \             'dynamicRegistration': v:false,
205       \             'codeActionLiteralSupport': {
206       \                  'codeActionKind': {
207       \                      'valueSet': []
208       \                  }
209       \              }
210       \           },
211       \           'rename': {
212       \             'dynamicRegistration': v:false,
213       \           },
214       \         },
215       \       },
216       \     },
217       \   },
218       \ ],
219       \ l:messages
220
221       call SendMessage({
222       \ 'jsonrpc': '2.0',
223       \ 'id': 1,
224       \ 'result': {
225       \   'capabilities': {
226       \     'renameProvider': v:true,
227       \     'executeCommandProvider': {
228       \       'commands': [],
229       \     },
230       \     'hoverProvider': v:true,
231       \     'documentSymbolProvider': v:true,
232       \     'documentRangeFormattingProvider': v:true,
233       \     'codeLensProvider': {
234       \       'resolveProvider': v:false
235       \     },
236       \     'referencesProvider': v:true,
237       \     'textDocumentSync': 2,
238       \     'documentFormattingProvider': v:true,
239       \     'codeActionProvider': v:true,
240       \     'signatureHelpProvider': {
241       \       'triggerCharacters': ['(', ','],
242       \     },
243       \     'completionProvider': {
244       \       'triggerCharacters': ['.'],
245       \       'resolveProvider': v:false
246       \     },
247       \     'definitionProvider': v:true,
248       \     'experimental': {},
249       \     'documentHighlightProvider': v:true,
250       \     'workspaceSymbolProvider': v:true,
251       \   },
252       \ },
253       \})
254
255       let l:messages = PopMessages()
256
257       AssertEqual
258       \ [
259       \   {
260       \     'method': 'initialized',
261       \     'jsonrpc': '2.0',
262       \     'params': {},
263       \   },
264       \   {
265       \     'method': 'textDocument/didOpen',
266       \     'jsonrpc': '2.0',
267       \     'params': {
268       \       'textDocument': {
269       \         'uri': ale#path#ToFileURI(expand('#' . a:buffer . ':p')),
270       \         'version': ale#lsp#message#GetNextVersionID() - 1,
271       \         'languageId': a:language,
272       \         'text': "\n",
273       \       },
274       \     },
275       \   },
276       \ ],
277       \ l:messages
278     endif
279
280     AssertEqual
281     \ [
282     \   [
283     \     a:linter_name,
284     \     {
285     \       'connection_id': a:conn_prefix . ':' . a:root,
286     \       'project_root': a:root,
287     \       'buffer': a:buffer,
288     \       'command': !empty(a:command) ? ale#job#PrepareCommand(a:buffer, a:command) : '',
289     \     },
290     \   ],
291     \ ],
292     \ g:calls
293   endfunction
294
295   function! AssertInitFailure() abort
296     let l:messages = PopMessages()
297
298     AssertEqual [], l:messages
299     AssertEqual [], g:calls
300   endfunction
301
302   call ale#linter#Reset()
303
304 After:
305   Restore
306
307   call ale#linter#Reset()
308   call ale#lsp#ResetConnections()
309
310   unlet! g:ale_run_synchronously_callbacks
311   unlet! g:job_map
312   unlet! g:emulate_job_failure
313   unlet! g:next_job_id
314   unlet! g:lsp_started
315
316   unlet! g:socket_map
317   unlet! g:emulate_socket_failure
318   unlet! g:next_channel_id
319
320   unlet! g:message_buffer
321   unlet! g:calls
322
323   augroup VaderTest
324     autocmd!
325   augroup END
326
327   augroup! VaderTest
328
329   delfunction PopMessages
330   delfunction Start
331   delfunction AssertInitSuccess
332   delfunction AssertInitFailure
333
334   runtime autoload/ale/engine.vim
335   runtime autoload/ale/job.vim
336   runtime autoload/ale/socket.vim
337
338 Execute(tsserver should be started correctly):
339   runtime ale_linters/typescript/tsserver.vim
340
341   Assert Start(bufnr(''))
342   call AssertInitSuccess('tsserver', 'tsserver', '', '', ale#Escape('tsserver'), bufnr(''))
343
344 Execute(tsserver failures should be handled appropriately):
345   runtime ale_linters/typescript/tsserver.vim
346
347   let g:emulate_job_failure = 1
348
349   Assert !Start(bufnr(''))
350   call AssertInitFailure()
351
352 Execute(LSP jobs should start correctly):
353   call ale#linter#Define('foobar', {
354   \   'name': 'foo',
355   \   'lsp': 'stdio',
356   \   'executable': 'foo',
357   \   'command': 'foo',
358   \   'project_root': '/foo/bar',
359   \   'initialization_options': {},
360   \})
361
362   Assert Start(bufnr(''))
363   call AssertInitSuccess('foo', 'foo', 'foobar', '/foo/bar', 'foo', bufnr(''))
364
365 Execute(LSP job failures should be handled):
366   call ale#linter#Define('foobar', {
367   \   'name': 'foo',
368   \   'lsp': 'stdio',
369   \   'executable': 'foo',
370   \   'command': 'foo',
371   \   'project_root': '/foo/bar',
372   \   'initialization_options': {},
373   \})
374
375   let g:emulate_job_failure = 1
376
377   Assert !Start(bufnr(''))
378   call AssertInitFailure()
379
380 Execute(LSP TCP connections should start correctly):
381   call ale#linter#Define('foobar', {
382   \   'name': 'foo',
383   \   'lsp': 'socket',
384   \   'address': 'foo',
385   \   'project_root': '/foo/bar',
386   \   'initialization_options': {},
387   \})
388
389   Assert Start(bufnr(''))
390   call AssertInitSuccess('foo', 'foo', 'foobar', '/foo/bar', '', bufnr(''))
391
392 Execute(LSP TCP connection failures should be handled):
393   call ale#linter#Define('foobar', {
394   \   'name': 'foo',
395   \   'lsp': 'socket',
396   \   'address': 'foo',
397   \   'project_root': '/foo/bar',
398   \   'initialization_options': {},
399   \})
400
401   let g:emulate_socket_failure = 1
402
403   Assert !Start(bufnr(''))
404   call AssertInitFailure()
405
406 Execute(Deferred executables should be handled correctly):
407   call ale#linter#Define('foobar', {
408   \   'name': 'foo',
409   \   'lsp': 'stdio',
410   \   'executable': {b -> ale#command#Run(b, 'echo', {-> 'foo'})},
411   \   'command': '%e -c',
412   \   'project_root': '/foo/bar',
413   \   'initialization_options': {},
414   \})
415
416   Assert Start(bufnr(''))
417   call ale#test#FlushJobs()
418   call AssertInitSuccess('foo', 'foo', 'foobar', '/foo/bar', ale#Escape('foo') . ' -c', bufnr(''))
419
420 Execute(Deferred commands should be handled correctly):
421   call ale#linter#Define('foobar', {
422   \   'name': 'foo',
423   \   'lsp': 'stdio',
424   \   'executable': 'foo',
425   \   'command': {b -> ale#command#Run(b, 'echo', {-> '%e -c'})},
426   \   'project_root': '/foo/bar',
427   \   'initialization_options': {},
428   \})
429
430   Assert Start(bufnr(''))
431   call ale#test#FlushJobs()
432   call AssertInitSuccess('foo', 'foo', 'foobar', '/foo/bar', ale#Escape('foo') . ' -c', bufnr(''))
433
434 Execute(Deferred addresses should be handled correctly):
435   call ale#linter#Define('foobar', {
436   \   'name': 'foo',
437   \   'lsp': 'socket',
438   \   'address': {b -> ale#command#Run(b, 'echo', {-> 'localhost:1234'})},
439   \   'project_root': '/foo/bar',
440   \   'initialization_options': {},
441   \})
442
443   Assert Start(bufnr(''))
444   call ale#test#FlushJobs()
445   call AssertInitSuccess('foo', 'localhost:1234', 'foobar', '/foo/bar', '', bufnr(''))
446
447 Execute(Servers that have crashed should be restarted):
448   call ale#lsp#Register('foo', '/foo/bar', '', {})
449   call extend(ale#lsp#GetConnections()['foo:/foo/bar'], {'initialized': 1})
450
451   " Starting the program again should reset initialized to `0`.
452   call ale#lsp#StartProgram('foo:/foo/bar', 'foobar', 'foobar --start')
453
454   AssertEqual 0, ale#lsp#GetConnections()['foo:/foo/bar']['initialized']
455   AssertEqual ['initialize'], map(PopMessages(), 'v:val[''method'']')
456
457 Execute(Current LSP buffer should receive ALELSPStarted):
458   call ale#linter#Define('foobar', {
459   \   'name': 'foo',
460   \   'lsp': 'socket',
461   \   'address': 'foo',
462   \   'project_root': '/foo/bar',
463   \   'initialization_options': {},
464   \})
465
466   augroup VaderTest
467     autocmd!
468     autocmd User ALELSPStarted let g:lsp_started = 1
469   augroup END
470
471   Assert Start(bufnr(''))
472   call AssertInitSuccess('foo', 'foo', 'foobar', '/foo/bar', '', bufnr(''))
473   AssertEqual g:lsp_started, 1
474
475 Execute(Target LSP buffer should receive ALELSPStarted):
476   call ale#linter#Define('foobar', {
477   \   'name': 'foo',
478   \   'lsp': 'socket',
479   \   'address': 'foo',
480   \   'project_root': '/foo/bar',
481   \   'initialization_options': {},
482   \})
483
484   augroup VaderTest
485     autocmd!
486     autocmd User ALELSPStarted let g:lsp_started = 1
487   augroup END
488
489   let buffer = bufnr('')
490
491   enew!
492   Assert Start(buffer)
493   call AssertInitSuccess('foo', 'foo', 'foobar', '/foo/bar', '', buffer)
494   execute 'buffer' . buffer
495
496   AssertEqual g:lsp_started, 1