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.
1 " Author: Jerko Steiner <jerko.steiner@gmail.com>
2 " Description: Rename symbol support for LSP / tsserver
6 " Used to get the rename map in tests.
7 function! ale#rename#GetMap() abort
8 return deepcopy(s:rename_map)
11 " Used to set the rename map in tests.
12 function! ale#rename#SetMap(map) abort
13 let s:rename_map = a:map
16 function! ale#rename#ClearLSPData() abort
20 let g:ale_rename_tsserver_find_in_comments = get(g:, 'ale_rename_tsserver_find_in_comments', v:false)
21 let g:ale_rename_tsserver_find_in_strings = get(g:, 'ale_rename_tsserver_find_in_strings', v:false)
23 function! s:message(message) abort
24 call ale#util#Execute('echom ' . string(a:message))
27 function! ale#rename#HandleTSServerResponse(conn_id, response) abort
28 if get(a:response, 'command', '') isnot# 'rename'
32 if !has_key(s:rename_map, a:response.request_seq)
36 let l:options = remove(s:rename_map, a:response.request_seq)
38 let l:old_name = l:options.old_name
39 let l:new_name = l:options.new_name
41 if get(a:response, 'success', v:false) is v:false
42 let l:message = get(a:response, 'message', 'unknown')
43 call s:message('Error renaming "' . l:old_name . '" to: "' . l:new_name
44 \ . '". Reason: ' . l:message)
51 for l:response_item in a:response.body.locs
52 let l:filename = l:response_item.file
53 let l:text_changes = []
55 for l:loc in l:response_item.locs
56 call add(l:text_changes, {
58 \ 'line': l:loc.start.line,
59 \ 'offset': l:loc.start.offset,
62 \ 'line': l:loc.end.line,
63 \ 'offset': l:loc.end.offset,
65 \ 'newText': l:new_name,
70 \ 'fileName': l:filename,
71 \ 'textChanges': l:text_changes,
76 call s:message('Error renaming "' . l:old_name . '" to: "' . l:new_name . '"')
81 call ale#code_action#HandleCodeAction(
83 \ 'description': 'rename',
84 \ 'changes': l:changes,
87 \ 'conn_id': a:conn_id,
88 \ 'should_save': g:ale_save_hidden || !&hidden,
93 function! ale#rename#HandleLSPResponse(conn_id, response) abort
94 if has_key(a:response, 'id')
95 \&& has_key(s:rename_map, a:response.id)
96 let l:options = remove(s:rename_map, a:response.id)
98 if !has_key(a:response, 'result')
99 call s:message('No rename result received from server')
104 let l:changes_map = ale#code_action#GetChanges(a:response.result)
106 if empty(l:changes_map)
107 call s:message('No changes received from server')
112 let l:changes = ale#code_action#BuildChangesList(l:changes_map)
114 call ale#code_action#HandleCodeAction(
116 \ 'description': 'rename',
117 \ 'changes': l:changes,
120 \ 'conn_id': a:conn_id,
121 \ 'should_save': g:ale_save_hidden || !&hidden,
127 function! s:OnReady(line, column, options, linter, lsp_details) abort
128 let l:id = a:lsp_details.connection_id
130 if !ale#lsp#HasCapability(l:id, 'rename')
134 let l:buffer = a:lsp_details.buffer
136 let l:Callback = a:linter.lsp is# 'tsserver'
137 \ ? function('ale#rename#HandleTSServerResponse')
138 \ : function('ale#rename#HandleLSPResponse')
140 call ale#lsp#RegisterCallback(l:id, l:Callback)
142 if a:linter.lsp is# 'tsserver'
143 let l:message = ale#lsp#tsserver_message#Rename(
147 \ g:ale_rename_tsserver_find_in_comments,
148 \ g:ale_rename_tsserver_find_in_strings,
151 " Send a message saying the buffer has changed first, or the
152 " rename position probably won't make sense.
153 call ale#lsp#NotifyForChanges(l:id, l:buffer)
155 let l:message = ale#lsp#message#Rename(
163 let l:request_id = ale#lsp#Send(l:id, l:message)
165 let s:rename_map[l:request_id] = a:options
168 function! s:ExecuteRename(linter, options) abort
169 let l:buffer = bufnr('')
170 let [l:line, l:column] = getpos('.')[1:2]
172 if a:linter.lsp isnot# 'tsserver'
173 let l:column = min([l:column, len(getline(l:line))])
176 let l:Callback = function('s:OnReady', [l:line, l:column, a:options])
177 call ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
180 function! ale#rename#Execute() abort
181 let l:linters = ale#lsp_linter#GetEnabled(bufnr(''))
184 call s:message('No active LSPs')
189 let l:old_name = expand('<cword>')
190 let l:new_name = ale#util#Input('New name: ', l:old_name)
193 call s:message('New name cannot be empty!')
198 for l:linter in l:linters
199 call s:ExecuteRename(l:linter, {
200 \ 'old_name': l:old_name,
201 \ 'new_name': l:new_name,