]> git.madduck.net Git - etc/vim.git/blob - autoload/ale/references.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:

Squashed '.vim/bundle/ale/' content from commit 22185c4c
[etc/vim.git] / autoload / ale / references.vim
1 let g:ale_default_navigation = get(g:, 'ale_default_navigation', 'buffer')
2
3 let s:references_map = {}
4
5 " Used to get the references map in tests.
6 function! ale#references#GetMap() abort
7     return deepcopy(s:references_map)
8 endfunction
9
10 " Used to set the references map in tests.
11 function! ale#references#SetMap(map) abort
12     let s:references_map = a:map
13 endfunction
14
15 function! ale#references#ClearLSPData() abort
16     let s:references_map = {}
17 endfunction
18
19 function! ale#references#FormatTSResponseItem(response_item, options) abort
20     let l:match = substitute(a:response_item.lineText, '^\s*\(.\{-}\)\s*$', '\1', '')
21
22     if get(a:options, 'open_in') is# 'quickfix'
23         return {
24         \ 'filename': a:response_item.file,
25         \ 'lnum': a:response_item.start.line,
26         \ 'col': a:response_item.start.offset,
27         \ 'text': l:match,
28         \}
29     else
30         return {
31         \ 'filename': a:response_item.file,
32         \ 'line': a:response_item.start.line,
33         \ 'column': a:response_item.start.offset,
34         \ 'match': l:match,
35         \}
36     endif
37 endfunction
38
39 function! ale#references#HandleTSServerResponse(conn_id, response) abort
40     if get(a:response, 'command', '') is# 'references'
41     \&& has_key(s:references_map, a:response.request_seq)
42         let l:options = remove(s:references_map, a:response.request_seq)
43
44         if get(a:response, 'success', v:false) is v:true
45             let l:item_list = []
46
47             for l:response_item in a:response.body.refs
48                 call add(
49                 \ l:item_list,
50                 \ ale#references#FormatTSResponseItem(l:response_item, l:options)
51                 \)
52             endfor
53
54             if empty(l:item_list)
55                 call ale#util#Execute('echom ''No references found.''')
56             else
57                 if get(l:options, 'open_in') is# 'quickfix'
58                     call setqflist([], 'r')
59                     call setqflist(l:item_list, 'a')
60                     call ale#util#Execute('cc 1')
61                 else
62                     call ale#preview#ShowSelection(l:item_list, l:options)
63                 endif
64             endif
65         endif
66     endif
67 endfunction
68
69 function! ale#references#FormatLSPResponseItem(response_item, options) abort
70     if get(a:options, 'open_in') is# 'quickfix'
71         return {
72         \ 'filename': ale#util#ToResource(a:response_item.uri),
73         \ 'lnum': a:response_item.range.start.line + 1,
74         \ 'col': a:response_item.range.start.character + 1,
75         \}
76     else
77         return {
78         \ 'filename': ale#util#ToResource(a:response_item.uri),
79         \ 'line': a:response_item.range.start.line + 1,
80         \ 'column': a:response_item.range.start.character + 1,
81         \}
82     endif
83 endfunction
84
85 function! ale#references#HandleLSPResponse(conn_id, response) abort
86     if has_key(a:response, 'id')
87     \&& has_key(s:references_map, a:response.id)
88         let l:options = remove(s:references_map, a:response.id)
89
90         " The result can be a Dictionary item, a List of the same, or null.
91         let l:result = get(a:response, 'result', [])
92         let l:item_list = []
93
94         if type(l:result) is v:t_list
95             for l:response_item in l:result
96                 call add(l:item_list,
97                 \ ale#references#FormatLSPResponseItem(l:response_item, l:options)
98                 \)
99             endfor
100         endif
101
102         if empty(l:item_list)
103             call ale#util#Execute('echom ''No references found.''')
104         else
105             if get(l:options, 'open_in') is# 'quickfix'
106                 call setqflist([], 'r')
107                 call setqflist(l:item_list, 'a')
108                 call ale#util#Execute('cc 1')
109             else
110                 call ale#preview#ShowSelection(l:item_list, l:options)
111             endif
112         endif
113     endif
114 endfunction
115
116 function! s:OnReady(line, column, options, linter, lsp_details) abort
117     let l:id = a:lsp_details.connection_id
118
119     if !ale#lsp#HasCapability(l:id, 'references')
120         return
121     endif
122
123     let l:buffer = a:lsp_details.buffer
124
125     let l:Callback = a:linter.lsp is# 'tsserver'
126     \   ? function('ale#references#HandleTSServerResponse')
127     \   : function('ale#references#HandleLSPResponse')
128
129     call ale#lsp#RegisterCallback(l:id, l:Callback)
130
131     if a:linter.lsp is# 'tsserver'
132         let l:message = ale#lsp#tsserver_message#References(
133         \   l:buffer,
134         \   a:line,
135         \   a:column
136         \)
137     else
138         " Send a message saying the buffer has changed first, or the
139         " references position probably won't make sense.
140         call ale#lsp#NotifyForChanges(l:id, l:buffer)
141
142         let l:message = ale#lsp#message#References(l:buffer, a:line, a:column)
143     endif
144
145     let l:request_id = ale#lsp#Send(l:id, l:message)
146
147     let s:references_map[l:request_id] = {
148     \ 'use_relative_paths': has_key(a:options, 'use_relative_paths') ? a:options.use_relative_paths : 0,
149     \ 'open_in': get(a:options, 'open_in', 'current-buffer'),
150     \}
151 endfunction
152
153 function! ale#references#Find(...) abort
154     let l:options = {}
155
156     if len(a:000) > 0
157         for l:option in a:000
158             if l:option is? '-relative'
159                 let l:options.use_relative_paths = 1
160             elseif l:option is? '-tab'
161                 let l:options.open_in = 'tab'
162             elseif l:option is? '-split'
163                 let l:options.open_in = 'split'
164             elseif l:option is? '-vsplit'
165                 let l:options.open_in = 'vsplit'
166             elseif l:option is? '-quickfix'
167                 let l:options.open_in = 'quickfix'
168             endif
169         endfor
170     endif
171
172     if !has_key(l:options, 'open_in')
173         let l:default_navigation = ale#Var(bufnr(''), 'default_navigation')
174
175         if index(['tab', 'split', 'vsplit'], l:default_navigation) >= 0
176             let l:options.open_in = l:default_navigation
177         endif
178     endif
179
180     let l:buffer = bufnr('')
181     let [l:line, l:column] = getpos('.')[1:2]
182     let l:column = min([l:column, len(getline(l:line))])
183     let l:Callback = function('s:OnReady', [l:line, l:column, l:options])
184
185     for l:linter in ale#lsp_linter#GetEnabled(l:buffer)
186         call ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
187     endfor
188 endfunction