]> git.madduck.net Git - etc/vim.git/blob - .vim/bundle/vim-lsp/autoload/lsp/internal/document_code_action/signs.vim

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 '56df844d3c39ec494dacc69eae34272b27db185a' as '.vim/bundle/asyncomplete'
[etc/vim.git] / .vim / bundle / vim-lsp / autoload / lsp / internal / document_code_action / signs.vim
1 " https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction
2
3 " internal state for whether it is enabled or not to avoid multiple subscriptions
4 let s:enabled = 0
5
6 let s:sign_group = 'vim_lsp_document_code_action_signs'
7
8 if !hlexists('LspCodeActionText')
9     highlight link LspCodeActionText Normal
10 endif
11
12 function! lsp#internal#document_code_action#signs#_enable() abort
13     if !lsp#utils#_has_signs() | return | endif
14     " don't even bother registering if the feature is disabled
15     if !g:lsp_document_code_action_signs_enabled | return | endif
16
17     if s:enabled | return | endif
18     let s:enabled = 1
19
20     call s:define_sign('LspCodeAction', 'A>', g:lsp_document_code_action_signs_hint)
21
22     " Note:
23     " - update CodeAction signs when CusorMoved or CursorHold
24     " - clear signs when InsertEnter or BufLeave
25     " - debounce code action requests
26     " - automatically switch to latest code action request via switchMap()
27     " - cancel code action request via takeUntil() when BufLeave
28     let s:Dispose = lsp#callbag#pipe(
29         \ lsp#callbag#merge(
30         \   lsp#callbag#fromEvent(['CursorMoved', 'CursorHold']),
31         \   lsp#callbag#pipe(
32         \       lsp#callbag#fromEvent(['InsertEnter', 'BufLeave']),
33         \       lsp#callbag#tap({_ -> s:clear_signs() }),
34         \   )
35         \ ),
36         \ lsp#callbag#filter({_ -> g:lsp_document_code_action_signs_enabled }),
37         \ lsp#callbag#debounceTime(g:lsp_document_code_action_signs_delay),
38         \ lsp#callbag#map({_->{'bufnr': bufnr('%'), 'curpos': getcurpos()[0:2], 'changedtick': b:changedtick }}),
39         \ lsp#callbag#distinctUntilChanged({a,b -> a['bufnr'] == b['bufnr'] && a['curpos'] == b['curpos'] && a['changedtick'] == b['changedtick']}),
40         \ lsp#callbag#filter({_->mode() is# 'n' && getbufvar(bufnr('%'), '&buftype') !=# 'terminal' }),
41         \ lsp#callbag#switchMap({_->
42         \   lsp#callbag#pipe(
43         \       s:send_request(),
44         \       lsp#callbag#materialize(),
45         \       lsp#callbag#filter({x->lsp#callbag#isNextNotification(x)}),
46         \       lsp#callbag#map({x->x['value']}),
47         \       lsp#callbag#takeUntil(
48         \           lsp#callbag#fromEvent('BufLeave')
49         \       )
50         \   )
51         \ }),
52         \ lsp#callbag#subscribe({x->s:set_signs(x)}),
53         \)
54 endfunction
55
56 function! lsp#internal#document_code_action#signs#_disable() abort
57     if !s:enabled | return | endif
58     if exists('s:Dispose')
59         call s:Dispose()
60         unlet s:Dispose
61     endif
62 endfunction
63
64 function! s:send_request() abort
65     let l:servers = filter(lsp#get_allowed_servers(), 'lsp#capabilities#has_code_action_provider(v:val)')
66
67     if empty(l:servers)
68         return lsp#callbag#empty()
69     endif
70
71     let l:range = lsp#utils#range#_get_current_line_range()
72     return lsp#callbag#pipe(
73         \ lsp#callbag#fromList(l:servers),
74         \ lsp#callbag#flatMap({server->
75         \   lsp#request(server, {
76         \       'method': 'textDocument/codeAction',
77         \       'params': {
78         \           'textDocument': lsp#get_text_document_identifier(),
79         \           'range': l:range,
80         \           'context': {
81         \               'diagnostics': [],
82         \               'only': ['', 'quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite'],
83         \           }
84         \       }
85         \   })
86         \ }),
87         \ lsp#callbag#filter({x-> !lsp#client#is_error(x['response']) && !empty(x['response']['result'])}),
88         \ lsp#callbag#take(1),
89         \ )
90 endfunction
91
92 function! s:clear_signs() abort
93     call sign_unplace(s:sign_group)
94 endfunction
95
96 function! s:set_signs(data) abort
97     call s:clear_signs()
98
99     if lsp#client#is_error(a:data['response']) | return | endif
100
101     if empty(a:data['response']['result'])
102         return
103     endif
104
105     let l:bufnr = bufnr(lsp#utils#uri_to_path(a:data['request']['params']['textDocument']['uri']))
106     call s:place_signs(a:data, l:bufnr)
107 endfunction
108
109 " Set default sign text to handle case when user provides empty dict
110 function! s:define_sign(sign_name, sign_default_text, sign_options) abort
111     let l:options = {
112         \ 'text': get(a:sign_options, 'text', a:sign_default_text),
113         \ 'texthl': a:sign_name . 'Text',
114         \ 'linehl': a:sign_name . 'Line',
115         \ }
116     let l:sign_icon = get(a:sign_options, 'icon', '')
117     if !empty(l:sign_icon)
118         let l:options['icon'] = l:sign_icon
119     endif
120     call sign_define(a:sign_name, l:options)
121 endfunction
122
123 function! s:place_signs(data, bufnr) abort
124     if !bufexists(a:bufnr) || !bufloaded(a:bufnr)
125         return
126     endif
127     let l:sign_priority = g:lsp_document_code_action_signs_priority
128     let l:line = lsp#utils#position#lsp_line_to_vim(a:bufnr, a:data['request']['params']['range']['start'])
129     let l:sign_id = sign_place(0, s:sign_group, 'LspCodeAction', a:bufnr, 
130         \ { 'lnum': l:line, 'priority': l:sign_priority })
131 endfunction