mirror of
https://github.com/prabirshrestha/vim-lsp.git
synced 2025-12-14 20:35:59 +01:00
fix eat of typing char after completion done (#1468)
When using typescript-language-server, in content `Math.ab|`, if you type `<C-X><C-o>` for omni completion, it will be completed with `s`. Then, the content will become `Math.abs|`. If you continue typing `(`, the `(` will be removed. Also, if type `<CR>`, a new line will be added, resulting in `Math.abs|s\nMath.ab`. This patch attempts to fix this issue.
This commit is contained in:
@@ -311,44 +311,43 @@ function! lsp#omni#get_vim_completion_items(options) abort
|
|||||||
\ 'icase': 1,
|
\ 'icase': 1,
|
||||||
\ }
|
\ }
|
||||||
let l:range = lsp#utils#text_edit#get_range(get(l:completion_item, 'textEdit', {}))
|
let l:range = lsp#utils#text_edit#get_range(get(l:completion_item, 'textEdit', {}))
|
||||||
|
let l:complete_word = ''
|
||||||
if has_key(l:completion_item, 'textEdit') && type(l:completion_item['textEdit']) == s:t_dict && !empty(l:range) && has_key(l:completion_item['textEdit'], 'newText')
|
if has_key(l:completion_item, 'textEdit') && type(l:completion_item['textEdit']) == s:t_dict && !empty(l:range) && has_key(l:completion_item['textEdit'], 'newText')
|
||||||
let l:text_edit_new_text = l:completion_item['textEdit']['newText']
|
let l:text_edit_new_text = l:completion_item['textEdit']['newText']
|
||||||
if has_key(l:completion_item, 'filterText') && !empty(l:completion_item['filterText']) && matchstr(l:text_edit_new_text, '^' . l:refresh_pattern) ==# ''
|
if has_key(l:completion_item, 'filterText') && !empty(l:completion_item['filterText']) && matchstr(l:text_edit_new_text, '^' . l:refresh_pattern) ==# ''
|
||||||
" Use filterText as word.
|
" Use filterText as word.
|
||||||
let l:vim_complete_item['word'] = l:completion_item['filterText']
|
let l:complete_word = l:completion_item['filterText']
|
||||||
else
|
else
|
||||||
" Use textEdit.newText as word.
|
" Use textEdit.newText as word.
|
||||||
let l:vim_complete_item['word'] = l:text_edit_new_text
|
let l:complete_word = l:text_edit_new_text
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Fix overlapped text if needed.
|
|
||||||
let l:item_start_character = l:range['start']['character']
|
let l:item_start_character = l:range['start']['character']
|
||||||
if l:item_start_character < l:default_start_character
|
|
||||||
" Add already typed word. The typescript-language-server returns `[Symbol]` item for the line of `Hoo.|`. So we should add `.` (`.[Symbol]`) .
|
|
||||||
let l:overlap_text = strcharpart(l:current_line, l:item_start_character, l:default_start_character - l:item_start_character)
|
|
||||||
if stridx(l:vim_complete_item['word'], l:overlap_text) != 0
|
|
||||||
let l:vim_complete_item['word'] = l:overlap_text . l:vim_complete_item['word']
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
let l:start_character = min([l:item_start_character, l:start_character])
|
let l:start_character = min([l:item_start_character, l:start_character])
|
||||||
let l:start_characters += [l:item_start_character]
|
let l:start_characters += [l:item_start_character]
|
||||||
elseif has_key(l:completion_item, 'insertText') && !empty(l:completion_item['insertText'])
|
elseif has_key(l:completion_item, 'insertText') && !empty(l:completion_item['insertText'])
|
||||||
let l:vim_complete_item['word'] = l:completion_item['insertText']
|
let l:complete_word = l:completion_item['insertText']
|
||||||
let l:start_characters += [l:default_start_character]
|
let l:start_characters += [l:default_start_character]
|
||||||
else
|
else
|
||||||
let l:vim_complete_item['word'] = l:completion_item['label']
|
let l:complete_word = l:completion_item['label']
|
||||||
let l:start_characters += [l:default_start_character]
|
let l:start_characters += [l:default_start_character]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if l:expandable
|
if l:expandable
|
||||||
let l:vim_complete_item['word'] = lsp#utils#make_valid_word(substitute(l:vim_complete_item['word'], '\$[0-9]\+\|\${\%(\\.\|[^}]\)\+}', '', 'g'))
|
let l:vim_complete_item['word'] = lsp#utils#make_valid_word(substitute(l:complete_word, '\$[0-9]\+\|\${\%(\\.\|[^}]\)\+}', '', 'g'))
|
||||||
let l:vim_complete_item['abbr'] = l:completion_item['label'] . '~'
|
let l:vim_complete_item['abbr'] = l:completion_item['label'] . '~'
|
||||||
else
|
else
|
||||||
|
let l:vim_complete_item['word'] = l:complete_word
|
||||||
let l:vim_complete_item['abbr'] = l:completion_item['label']
|
let l:vim_complete_item['abbr'] = l:completion_item['label']
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if s:is_user_data_support
|
if s:is_user_data_support
|
||||||
let l:vim_complete_item['user_data'] = s:create_user_data(l:completion_item, l:server_name, l:complete_position, l:start_characters[len(l:start_characters) - 1])
|
let l:vim_complete_item['user_data'] = s:create_user_data(
|
||||||
|
\ l:completion_item,
|
||||||
|
\ l:server_name,
|
||||||
|
\ l:complete_position,
|
||||||
|
\ l:start_characters[-1],
|
||||||
|
\ l:complete_word)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:vim_complete_items += [l:vim_complete_item]
|
let l:vim_complete_items += [l:vim_complete_item]
|
||||||
@@ -382,13 +381,14 @@ endfunction
|
|||||||
"
|
"
|
||||||
" create item's user_data.
|
" create item's user_data.
|
||||||
"
|
"
|
||||||
function! s:create_user_data(completion_item, server_name, complete_position, start_character) abort
|
function! s:create_user_data(completion_item, server_name, complete_position, start_character, complete_word) abort
|
||||||
let l:user_data_key = s:create_user_data_key(s:managed_user_data_key_base)
|
let l:user_data_key = s:create_user_data_key(s:managed_user_data_key_base)
|
||||||
let s:managed_user_data_map[l:user_data_key] = {
|
let s:managed_user_data_map[l:user_data_key] = {
|
||||||
\ 'complete_position': a:complete_position,
|
\ 'complete_position': a:complete_position,
|
||||||
\ 'server_name': a:server_name,
|
\ 'server_name': a:server_name,
|
||||||
\ 'completion_item': a:completion_item,
|
\ 'completion_item': a:completion_item,
|
||||||
\ 'start_character': a:start_character,
|
\ 'start_character': a:start_character,
|
||||||
|
\ 'complete_word': a:complete_word,
|
||||||
\ }
|
\ }
|
||||||
let s:managed_user_data_key_base += 1
|
let s:managed_user_data_key_base += 1
|
||||||
return l:user_data_key
|
return l:user_data_key
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ function! s:on_complete_done() abort
|
|||||||
|
|
||||||
let s:context['done_line'] = getline('.')
|
let s:context['done_line'] = getline('.')
|
||||||
let s:context['done_line_nr'] = line('.')
|
let s:context['done_line_nr'] = line('.')
|
||||||
let s:context['completed_item'] = copy(v:completed_item)
|
|
||||||
let s:context['done_position'] = lsp#utils#position#vim_to_lsp('%', getpos('.')[1 : 2])
|
let s:context['done_position'] = lsp#utils#position#vim_to_lsp('%', getpos('.')[1 : 2])
|
||||||
let s:context['complete_position'] = l:managed_user_data['complete_position']
|
let s:context['complete_position'] = l:managed_user_data['complete_position']
|
||||||
let s:context['server_name'] = l:managed_user_data['server_name']
|
let s:context['server_name'] = l:managed_user_data['server_name']
|
||||||
let s:context['completion_item'] = l:managed_user_data['completion_item']
|
let s:context['completion_item'] = l:managed_user_data['completion_item']
|
||||||
let s:context['start_character'] = l:managed_user_data['start_character']
|
let s:context['start_character'] = l:managed_user_data['start_character']
|
||||||
|
let s:context['complete_word'] = l:managed_user_data['complete_word']
|
||||||
call feedkeys(printf("\<C-r>=<SNR>%d_on_complete_done_after()\<CR>", s:SID()), 'n')
|
call feedkeys(printf("\<C-r>=<SNR>%d_on_complete_done_after()\<CR>", s:SID()), 'n')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -73,12 +73,12 @@ function! s:on_complete_done_after() abort
|
|||||||
|
|
||||||
let l:done_line = s:context['done_line']
|
let l:done_line = s:context['done_line']
|
||||||
let l:done_line_nr = s:context['done_line_nr']
|
let l:done_line_nr = s:context['done_line_nr']
|
||||||
let l:completed_item = s:context['completed_item']
|
|
||||||
let l:done_position = s:context['done_position']
|
let l:done_position = s:context['done_position']
|
||||||
let l:complete_position = s:context['complete_position']
|
let l:complete_position = s:context['complete_position']
|
||||||
let l:server_name = s:context['server_name']
|
let l:server_name = s:context['server_name']
|
||||||
let l:completion_item = s:context['completion_item']
|
let l:completion_item = s:context['completion_item']
|
||||||
let l:start_character = s:context['start_character']
|
let l:start_character = s:context['start_character']
|
||||||
|
let l:complete_word = s:context['complete_word']
|
||||||
|
|
||||||
" check the commit characters are <BS> or <C-w>.
|
" check the commit characters are <BS> or <C-w>.
|
||||||
if line('.') ==# l:done_line_nr && strlen(getline('.')) < strlen(l:done_line)
|
if line('.') ==# l:done_line_nr && strlen(getline('.')) < strlen(l:done_line)
|
||||||
@@ -95,7 +95,7 @@ function! s:on_complete_done_after() abort
|
|||||||
let l:completion_item = s:resolve_completion_item(l:completion_item, l:server_name)
|
let l:completion_item = s:resolve_completion_item(l:completion_item, l:server_name)
|
||||||
|
|
||||||
" clear completed string if need.
|
" clear completed string if need.
|
||||||
let l:is_expandable = s:is_expandable(l:done_line, l:done_position, l:complete_position, l:completion_item, l:completed_item)
|
let l:is_expandable = s:is_expandable(l:done_line, l:done_position, l:complete_position, l:completion_item, l:complete_word)
|
||||||
if l:is_expandable
|
if l:is_expandable
|
||||||
call s:clear_auto_inserted_text(l:done_line, l:done_position, l:complete_position)
|
call s:clear_auto_inserted_text(l:done_line, l:done_position, l:complete_position)
|
||||||
endif
|
endif
|
||||||
@@ -162,7 +162,7 @@ endfunction
|
|||||||
"
|
"
|
||||||
" is_expandable
|
" is_expandable
|
||||||
"
|
"
|
||||||
function! s:is_expandable(done_line, done_position, complete_position, completion_item, completed_item) abort
|
function! s:is_expandable(done_line, done_position, complete_position, completion_item, complete_word) abort
|
||||||
if get(a:completion_item, 'textEdit', v:null) isnot# v:null
|
if get(a:completion_item, 'textEdit', v:null) isnot# v:null
|
||||||
let l:range = lsp#utils#text_edit#get_range(a:completion_item['textEdit'])
|
let l:range = lsp#utils#text_edit#get_range(a:completion_item['textEdit'])
|
||||||
if l:range['start']['line'] != l:range['end']['line']
|
if l:range['start']['line'] != l:range['end']['line']
|
||||||
@@ -177,7 +177,7 @@ function! s:is_expandable(done_line, done_position, complete_position, completio
|
|||||||
let l:text_edit_after = strcharpart(l:completed_line, l:range['end']['character'], strchars(l:completed_line) - l:range['end']['character'])
|
let l:text_edit_after = strcharpart(l:completed_line, l:range['end']['character'], strchars(l:completed_line) - l:range['end']['character'])
|
||||||
return a:done_line !=# l:text_edit_before . s:trim_unmeaning_tabstop(a:completion_item['textEdit']['newText']) . l:text_edit_after
|
return a:done_line !=# l:text_edit_before . s:trim_unmeaning_tabstop(a:completion_item['textEdit']['newText']) . l:text_edit_after
|
||||||
endif
|
endif
|
||||||
return s:get_completion_text(a:completion_item) !=# s:trim_unmeaning_tabstop(a:completed_item['word'])
|
return s:get_completion_text(a:completion_item) !=# s:trim_unmeaning_tabstop(a:complete_word)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
"
|
"
|
||||||
@@ -246,7 +246,7 @@ endfunction
|
|||||||
function! s:clear_auto_inserted_text(done_line, done_position, complete_position) abort
|
function! s:clear_auto_inserted_text(done_line, done_position, complete_position) abort
|
||||||
let l:before = strcharpart(a:done_line, 0, a:complete_position['character'])
|
let l:before = strcharpart(a:done_line, 0, a:complete_position['character'])
|
||||||
let l:after = strcharpart(a:done_line, a:done_position['character'], (strchars(a:done_line) - a:done_position['character']))
|
let l:after = strcharpart(a:done_line, a:done_position['character'], (strchars(a:done_line) - a:done_position['character']))
|
||||||
call setline('.', l:before . l:after)
|
call setline(a:done_position['line'] + 1, l:before . l:after)
|
||||||
call cursor([a:done_position['line'] + 1, strlen(l:before) + 1])
|
call cursor([a:done_position['line'] + 1, strlen(l:before) + 1])
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ Describe lsp#omni
|
|||||||
\ 'completion_item': item,
|
\ 'completion_item': item,
|
||||||
\ 'complete_position': { 'line': 1, 'character': 1 },
|
\ 'complete_position': { 'line': 1, 'character': 1 },
|
||||||
\ 'start_character': 0,
|
\ 'start_character': 0,
|
||||||
|
\ 'complete_word': 'yyy',
|
||||||
\ })
|
\ })
|
||||||
End
|
End
|
||||||
|
|
||||||
@@ -187,6 +188,7 @@ Describe lsp#omni
|
|||||||
\ 'completion_item': item,
|
\ 'completion_item': item,
|
||||||
\ 'complete_position': { 'line': 1, 'character': 1 },
|
\ 'complete_position': { 'line': 1, 'character': 1 },
|
||||||
\ 'start_character': 0,
|
\ 'start_character': 0,
|
||||||
|
\ 'complete_word': 'System.out.println(${0});',
|
||||||
\ })
|
\ })
|
||||||
End
|
End
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user