|
8 | 8 | function! lsp#ui#vim#code_lens#do(option) abort
|
9 | 9 | let l:sync = get(a:option, 'sync', v:false)
|
10 | 10 |
|
11 |
| - let l:server_names = filter(lsp#get_allowed_servers(), 'lsp#capabilities#has_code_lens_provider(v:val)') |
12 |
| - if len(l:server_names) == 0 |
| 11 | + let s:items = [] |
| 12 | + |
| 13 | + let l:servers = filter(lsp#get_allowed_servers(), 'lsp#capabilities#has_code_lens_provider(v:val)') |
| 14 | + if len(l:servers) == 0 |
13 | 15 | return lsp#utils#error('Code lens not supported for ' . &filetype)
|
14 | 16 | endif
|
15 | 17 |
|
16 |
| - let l:ctx = { |
17 |
| - \ 'count': len(l:server_names), |
18 |
| - \ 'results': [], |
19 |
| - \} |
| 18 | + redraw | echo 'Retrieving codelens ...' |
| 19 | + |
20 | 20 | let l:bufnr = bufnr('%')
|
21 |
| - let l:command_id = lsp#_new_command() |
22 |
| - for l:server_name in l:server_names |
23 |
| - call lsp#send_request(l:server_name, { |
24 |
| - \ 'method': 'textDocument/codeLens', |
25 |
| - \ 'params': { |
26 |
| - \ 'textDocument': lsp#get_text_document_identifier(), |
27 |
| - \ }, |
28 |
| - \ 'sync': l:sync, |
29 |
| - \ 'on_notification': function('s:handle_code_lens', [l:ctx, l:server_name, l:command_id, l:sync, l:bufnr]), |
30 |
| - \ }) |
31 |
| - endfor |
32 |
| - echo 'Retrieving code lenses ...' |
33 |
| -endfunction |
34 | 21 |
|
35 |
| -function! s:handle_code_lens(ctx, server_name, command_id, sync, bufnr, data) abort |
36 |
| - " Ignore old request. |
37 |
| - if a:command_id != lsp#_last_command() |
38 |
| - return |
39 |
| - endif |
| 22 | + call lsp#callbag#pipe( |
| 23 | + \ lsp#callbag#fromList(l:servers), |
| 24 | + \ lsp#callbag#flatMap({server-> |
| 25 | + \ lsp#callbag#pipe( |
| 26 | + \ lsp#request(server, { |
| 27 | + \ 'method': 'textDocument/codeLens', |
| 28 | + \ 'params': { |
| 29 | + \ 'textDocument': lsp#get_text_document_identifier(), |
| 30 | + \ }, |
| 31 | + \ }), |
| 32 | + \ lsp#callbag#flatMap({x->s:resolve_if_required(server, x['response'])}), |
| 33 | + \ lsp#callbag#map({x->{ 'server': server, 'codelens': x }}), |
| 34 | + \ ) |
| 35 | + \ }), |
| 36 | + \ lsp#callbag#takeUntil(lsp#callbag#pipe( |
| 37 | + \ lsp#stream(), |
| 38 | + \ lsp#callbag#filter({x->has_key(x, 'command')}), |
| 39 | + \ )), |
| 40 | + \ lsp#callbag#subscribe({ |
| 41 | + \ 'next':{x->add(s:items, x)}, |
| 42 | + \ 'complete': {->s:chooseCodeLens(s:items, l:bufnr)}, |
| 43 | + \ 'error': {e->s:error(x)}, |
| 44 | + \ }), |
| 45 | + \ ) |
| 46 | +endfunction |
40 | 47 |
|
41 |
| - call add(a:ctx['results'], { |
42 |
| - \ 'server_name': a:server_name, |
43 |
| - \ 'data': a:data, |
44 |
| - \}) |
45 |
| - let a:ctx['count'] -= 1 |
46 |
| - if a:ctx['count'] ># 0 |
47 |
| - return |
| 48 | +function! s:resolve_if_required(server, response) abort |
| 49 | + let l:codelens = a:response['result'] |
| 50 | + if empty(l:codelens) |
| 51 | + return lsp#callbag#empty() |
48 | 52 | endif
|
49 | 53 |
|
50 |
| - let l:total_code_lenses = [] |
51 |
| - for l:result in a:ctx['results'] |
52 |
| - let l:server_name = l:result['server_name'] |
53 |
| - let l:data = l:result['data'] |
54 |
| - " Check response error. |
55 |
| - if lsp#client#is_error(l:data['response']) |
56 |
| - call lsp#utils#error('Failed to CodeLens for ' . l:server_name . ': ' . lsp#client#error_message(l:data['response'])) |
57 |
| - continue |
58 |
| - endif |
59 |
| - |
60 |
| - " Check code lenses. |
61 |
| - let l:code_lenses = l:data['response']['result'] |
62 |
| - if empty(l:code_lenses) |
63 |
| - continue |
64 |
| - endif |
| 54 | + return lsp#callbag#pipe( |
| 55 | + \ lsp#callbag#fromList(l:codelens), |
| 56 | + \ lsp#callbag#flatMap({codelens-> has_key(codelens, 'command') ? lsp#callbag#of(codelens) : s:resolve_codelens(a:server, codelens) }), |
| 57 | + \ ) |
| 58 | +endfunction |
65 | 59 |
|
66 |
| - for l:code_lens in l:code_lenses |
67 |
| - call add(l:total_code_lenses, { |
68 |
| - \ 'server_name': l:server_name, |
69 |
| - \ 'code_lens': l:code_lens, |
70 |
| - \}) |
71 |
| - endfor |
72 |
| - endfor |
| 60 | +function! s:resolve_codelens(server, codelens) abort |
| 61 | + " TODO: return callbag#lsp#empty() if codelens resolve not supported by server |
| 62 | + return lsp#callbag#pipe( |
| 63 | + \ lsp#request(a:server, { |
| 64 | + \ 'method': 'codeLens/resolve', |
| 65 | + \ 'params': a:codelens |
| 66 | + \ }), |
| 67 | + \ lsp#callbag#map({x->x['response']['result']}), |
| 68 | + \ ) |
| 69 | +endfunction |
73 | 70 |
|
74 |
| - if len(l:total_code_lenses) == 0 |
75 |
| - echo 'No code lenses found' |
| 71 | +function! s:chooseCodeLens(items, bufnr) abort |
| 72 | + redraw | echo 'Select codelens:' |
| 73 | + if empty(a:items) |
| 74 | + call lsp#utils#error('No codelens found') |
76 | 75 | return
|
77 | 76 | endif
|
78 |
| - call lsp#log('s:handle_code_lens', l:total_code_lenses) |
79 |
| - |
80 |
| - " Prompt to choose code lenses. |
81 |
| - let l:index = inputlist(map(copy(l:total_code_lenses), { i, lens -> |
82 |
| - \ printf('%s - [%s] %s', i + 1, lens['server_name'], lens['code_lens']['command']['title']) |
83 |
| - \ })) |
84 |
| - |
85 |
| - " Execute code lens. |
86 |
| - if 0 < l:index && l:index <= len(l:total_code_lenses) |
87 |
| - let l:selected = l:total_code_lenses[l:index - 1] |
88 |
| - call s:handle_one_code_lens(l:selected['server_name'], a:sync, a:bufnr, l:selected['code_lens']) |
| 77 | + let l:index = inputlist(map(copy(a:items), {i, value -> |
| 78 | + \ printf('%s - [%s] %s', i + 1, value['server'], value['codelens']['command']['title']) |
| 79 | + \ })) |
| 80 | + if l:index > 0 && l:index <= len(a:items) |
| 81 | + let l:selected = a:items[l:index - 1] |
| 82 | + call s:handle_code_lens_command(l:selected['server'], l:selected['codelens'], a:bufnr) |
89 | 83 | endif
|
90 | 84 | endfunction
|
91 | 85 |
|
92 |
| -function! s:handle_one_code_lens(server_name, sync, bufnr, code_lens) abort |
| 86 | +function! s:error(e) abort |
| 87 | + call lsp#utils#error('Echo occured during CodeLens' . a:e) |
| 88 | +endfunction |
| 89 | + |
| 90 | +function! s:handle_code_lens_command(server, codelens, bufnr) abort |
93 | 91 | call lsp#ui#vim#execute_command#_execute({
|
94 |
| - \ 'server_name': a:server_name, |
95 |
| - \ 'command_name': get(a:code_lens['command'], 'command', ''), |
96 |
| - \ 'command_args': get(a:code_lens['command'], 'arguments', v:null), |
97 |
| - \ 'sync': a:sync, |
98 |
| - \ 'bufnr': a:bufnr, |
99 |
| - \ }) |
| 92 | + \ 'server_name': a:server, |
| 93 | + \ 'command_name': get(a:codelens['command'], 'command', ''), |
| 94 | + \ 'command_args': get(a:codelens['command'], 'arguments', v:null), |
| 95 | + \ 'sync': 0, |
| 96 | + \ 'bufnr': a:bufnr, |
| 97 | + \ }) |
100 | 98 | endfunction
|
0 commit comments