Read trigger characters from LSP initialize responses (#5121)
CI / Build (push) Has been cancelled
CI / Neovim 0.10 Windows (push) Has been cancelled
CI / Neovim 0.12 Windows (push) Has been cancelled
CI / Vim 8.2 Windows (push) Has been cancelled
CI / Vim 9.2 Windows (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Lua (push) Has been cancelled
CI / Neovim 0.10 Linux (push) Has been cancelled
CI / Neovim 0.12 Linux (push) Has been cancelled
CI / Vim 8.2 Linux (push) Has been cancelled
CI / Vim 9.2 Linux (push) Has been cancelled

* Add ale#lsp#GetCompletionTriggerCharacters getter
* Add s:GetTriggerCharacters helper with LSP support
* Pass connection ID to GetTriggerCharacter in s:OnReady
* Use LSP trigger characters in Filter function
* Add tests for LSP completion trigger characters
* Check LSP trigger characters in GetPrefix
* Add tests for GetAllCompletionTriggerCharactersForBuffer

GetTriggerCharacter now accepts optional conn_id parameter to
prefer LSP-provided trigger characters over the hardcoded map.

GetPrefix now checks if the line ends with any trigger character
from LSPs active for the current buffer, enabling automatic
completion for LSP-provided triggers like > for PHP.
This commit is contained in:
Eric Stern
2026-05-31 17:59:23 +01:00
committed by GitHub
parent 7a7fc85e51
commit 36d541facb
4 changed files with 173 additions and 5 deletions
+37 -5
View File
@@ -145,6 +145,7 @@ let s:omni_start_map = {
" A map of exact characters for triggering LSP completions. Do not forget to
" update self.input_patterns in ale.py in updating entries in this map.
" These are used as a fallback when LSP servers don't provide trigger chars.
let s:trigger_character_map = {
\ '<default>': ['.'],
\ 'typescript': ['.', '''', '"'],
@@ -153,6 +154,19 @@ let s:trigger_character_map = {
\ 'c': ['.', '->'],
\}
" Get trigger characters, preferring LSP-provided ones over hardcoded.
function! s:GetTriggerCharacters(filetype, conn_id) abort
if !empty(a:conn_id)
let l:lsp_triggers = ale#lsp#GetCompletionTriggerCharacters(a:conn_id)
if !empty(l:lsp_triggers)
return l:lsp_triggers
endif
endif
return s:GetFiletypeValue(s:trigger_character_map, a:filetype)
endfunction
function! s:GetFiletypeValue(map, filetype) abort
for l:part in reverse(split(a:filetype, '\.'))
let l:regex = get(a:map, l:part, [])
@@ -175,15 +189,32 @@ function! ale#completion#GetPrefix(filetype, line, column) abort
" abc
" ^
" So we need check the text in the column before that position.
return matchstr(getline(a:line)[: a:column - 2], l:regex)
let l:line_text = getline(a:line)[: a:column - 2]
let l:prefix = matchstr(l:line_text, l:regex)
if !empty(l:prefix)
return l:prefix
endif
" Check LSP trigger characters for active connections on this buffer.
let l:triggers = ale#lsp#GetAllCompletionTriggerCharactersForBuffer(bufnr(''))
for l:char in l:triggers
if l:line_text[-len(l:char):] is# l:char
return l:char
endif
endfor
return ''
endfunction
function! ale#completion#GetTriggerCharacter(filetype, prefix) abort
function! ale#completion#GetTriggerCharacter(filetype, prefix, ...) abort
if empty(a:prefix)
return ''
endif
let l:char_list = s:GetFiletypeValue(s:trigger_character_map, a:filetype)
let l:conn_id = get(a:, 1, '')
let l:char_list = s:GetTriggerCharacters(a:filetype, l:conn_id)
if index(l:char_list, a:prefix) >= 0
return a:prefix
@@ -204,7 +235,8 @@ function! ale#completion#Filter(
if empty(a:prefix)
let l:filtered_suggestions = a:suggestions
else
let l:triggers = s:GetFiletypeValue(s:trigger_character_map, a:filetype)
let l:conn_id = get(get(b:, 'ale_completion_info', {}), 'conn_id', '')
let l:triggers = s:GetTriggerCharacters(a:filetype, l:conn_id)
" For completing...
" foo.
@@ -805,7 +837,7 @@ function! s:OnReady(linter, lsp_details) abort
\ l:buffer,
\ b:ale_completion_info.line,
\ b:ale_completion_info.column,
\ ale#completion#GetTriggerCharacter(&filetype, b:ale_completion_info.prefix),
\ ale#completion#GetTriggerCharacter(&filetype, b:ale_completion_info.prefix, l:id),
\)
endif
+30
View File
@@ -1010,3 +1010,33 @@ function! ale#lsp#HasCapability(conn_id, capability) abort
return l:conn.capabilities[a:capability]
endfunction
" Get the completion trigger characters for a connection.
function! ale#lsp#GetCompletionTriggerCharacters(conn_id) abort
let l:conn = get(s:connections, a:conn_id, {})
if empty(l:conn)
return []
endif
return get(l:conn.capabilities, 'completion_trigger_characters', [])
endfunction
" Get all completion trigger characters from LSPs active for a buffer.
function! ale#lsp#GetAllCompletionTriggerCharactersForBuffer(buffer) abort
let l:all_triggers = []
for l:conn in values(s:connections)
if has_key(l:conn.open_documents, a:buffer)
let l:triggers = get(l:conn.capabilities, 'completion_trigger_characters', [])
for l:char in l:triggers
if index(l:all_triggers, l:char) < 0
call add(l:all_triggers, l:char)
endif
endfor
endif
endfor
return l:all_triggers
endfunction