mirror of
https://github.com/dense-analysis/ale.git
synced 2026-05-17 22:09:47 +08:00
Close #5112 - Support newer Pyright and other LSPs
Add support for dynamic capability registration for the diagnostic pull model to support Pyright >= 1.1.407 and other language servers. This is a rather complex and intricate change tested with Pyright and gopls, and may need further tweaking if something breaks with another server.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
Before:
|
||||
runtime autoload/ale/lsp.vim
|
||||
|
||||
Save g:ale_set_lists_synchronously
|
||||
Save g:ale_buffer_info
|
||||
Save g:ale_lsp_error_messages
|
||||
@@ -40,6 +42,7 @@ After:
|
||||
call ale#test#RestoreDirectory()
|
||||
call ale#linter#Reset()
|
||||
call ale#lsp_linter#ClearLSPData()
|
||||
call ale#lsp_linter#ClearDiagnosticURIMap()
|
||||
|
||||
Given foobar(An empty file):
|
||||
Execute(tsserver syntax error responses should be handled correctly):
|
||||
@@ -534,6 +537,60 @@ Execute(LSP pull model diagnostic responses that are 'unchanged' should be handl
|
||||
\ g:ale_buffer_info[bufnr('')].loclist
|
||||
AssertEqual [], g:ale_buffer_info[bufnr('')].active_linter_list
|
||||
|
||||
Execute(LSP pull model diagnostic errors should clear pending requests):
|
||||
let b:ale_linters = ['eclipselsp']
|
||||
runtime ale_linters/java/eclipselsp.vim
|
||||
|
||||
if has('win32')
|
||||
call ale#test#SetFilename('filename,[]^$.ts')
|
||||
else
|
||||
call ale#test#SetFilename('filename*?,{}[]^$.java')
|
||||
endif
|
||||
|
||||
call ale#engine#InitBufferInfo(bufnr(''))
|
||||
let g:ale_buffer_info[bufnr('')].loclist = [
|
||||
\ {
|
||||
\ 'lnum': 1,
|
||||
\ 'bufnr': bufnr(''),
|
||||
\ 'col': 1,
|
||||
\ 'pattern': '',
|
||||
\ 'valid': 1,
|
||||
\ 'vcol': 0,
|
||||
\ 'nr': -1,
|
||||
\ 'type': 'W',
|
||||
\ 'text': 'Missing JRE 1-8'
|
||||
\ },
|
||||
\]
|
||||
|
||||
call ale#lsp_linter#SetLSPLinterMap({'1': {'name': 'eclipselsp', 'aliases': [], 'lsp': 'stdio'}})
|
||||
call ale#lsp_linter#SetDiagnosticURIMap({'347': ale#util#ToURI(expand('%:p'))})
|
||||
|
||||
call ale#lsp_linter#HandleLSPResponse(1, {
|
||||
\ 'jsonrpc': '2.0',
|
||||
\ 'id': 347,
|
||||
\ 'error': {
|
||||
\ 'code': -32802,
|
||||
\ 'message': 'server cancelled',
|
||||
\ },
|
||||
\})
|
||||
|
||||
AssertEqual {}, ale#lsp_linter#GetDiagnosticURIMap()
|
||||
AssertEqual
|
||||
\ [
|
||||
\ {
|
||||
\ 'lnum': 1,
|
||||
\ 'bufnr': bufnr(''),
|
||||
\ 'col': 1,
|
||||
\ 'pattern': '',
|
||||
\ 'valid': 1,
|
||||
\ 'vcol': 0,
|
||||
\ 'nr': -1,
|
||||
\ 'type': 'W',
|
||||
\ 'text': 'Missing JRE 1-8'
|
||||
\ }
|
||||
\ ],
|
||||
\ g:ale_buffer_info[bufnr('')].loclist
|
||||
|
||||
Execute(workspace/configuration requests should be answered with the connection config):
|
||||
let g:sent_responses = []
|
||||
|
||||
@@ -564,26 +621,134 @@ Execute(workspace/configuration requests should be answered with the connection
|
||||
|
||||
Execute(client/registerCapability requests should be acknowledged):
|
||||
let g:sent_responses = []
|
||||
let g:registered_capabilities = []
|
||||
let g:sent_pull_diagnostics = []
|
||||
|
||||
function! ale#lsp#SendResponse(conn_id, id, result) abort
|
||||
call add(g:sent_responses, [a:conn_id, a:id, a:result])
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#RegisterCapabilities(conn_id, registrations) abort
|
||||
call add(g:registered_capabilities, [a:conn_id, a:registrations])
|
||||
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#SendDiagnosticsForOpenDocuments(conn_id) abort
|
||||
call add(g:sent_pull_diagnostics, a:conn_id)
|
||||
|
||||
return []
|
||||
endfunction
|
||||
|
||||
call ale#lsp_linter#SetLSPLinterMap({'1': {'name': 'expert', 'aliases': [], 'lsp': 'stdio'}})
|
||||
call ale#lsp_linter#HandleLSPResponse(1, {
|
||||
\ 'jsonrpc': '2.0',
|
||||
\ 'id': 12,
|
||||
\ 'method': 'client/registerCapability',
|
||||
\ 'params': {
|
||||
\ 'registrations': [{'id': 'abc', 'method': 'textDocument/didSave'}],
|
||||
\ 'registrations': [
|
||||
\ {
|
||||
\ 'id': 'abc',
|
||||
\ 'method': 'textDocument/diagnostic',
|
||||
\ 'registerOptions': {'interFileDependencies': v:true},
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\})
|
||||
|
||||
AssertEqual
|
||||
\ [[1, 12, v:null]],
|
||||
\ g:sent_responses
|
||||
AssertEqual
|
||||
\ [[1, [
|
||||
\ {
|
||||
\ 'id': 'abc',
|
||||
\ 'method': 'textDocument/diagnostic',
|
||||
\ 'registerOptions': {'interFileDependencies': v:true},
|
||||
\ },
|
||||
\ ]]],
|
||||
\ g:registered_capabilities
|
||||
AssertEqual [1], g:sent_pull_diagnostics
|
||||
|
||||
unlet! g:sent_responses
|
||||
unlet! g:registered_capabilities
|
||||
unlet! g:sent_pull_diagnostics
|
||||
runtime autoload/ale/lsp.vim
|
||||
|
||||
Execute(workspace/diagnostic/refresh requests should pull diagnostics):
|
||||
let g:sent_responses = []
|
||||
let g:sent_pull_diagnostics = []
|
||||
|
||||
function! ale#lsp#SendResponse(conn_id, id, result) abort
|
||||
call add(g:sent_responses, [a:conn_id, a:id, a:result])
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#SendDiagnosticsForOpenDocuments(conn_id) abort
|
||||
call add(g:sent_pull_diagnostics, a:conn_id)
|
||||
|
||||
return []
|
||||
endfunction
|
||||
|
||||
call ale#lsp_linter#SetLSPLinterMap({'1': {'name': 'expert', 'aliases': [], 'lsp': 'stdio'}})
|
||||
call ale#lsp_linter#SetDiagnosticURIMap({'13': 'file://foo.py'})
|
||||
|
||||
call ale#lsp_linter#HandleLSPResponse(1, {
|
||||
\ 'jsonrpc': '2.0',
|
||||
\ 'id': 13,
|
||||
\ 'method': 'workspace/diagnostic/refresh',
|
||||
\})
|
||||
|
||||
AssertEqual
|
||||
\ [[1, 13, v:null]],
|
||||
\ g:sent_responses
|
||||
AssertEqual [1], g:sent_pull_diagnostics
|
||||
AssertEqual {'13': 'file://foo.py'}, ale#lsp_linter#GetDiagnosticURIMap()
|
||||
|
||||
unlet! g:sent_responses
|
||||
unlet! g:sent_pull_diagnostics
|
||||
runtime autoload/ale/lsp.vim
|
||||
|
||||
Execute(client/unregisterCapability requests should unregister and be acknowledged):
|
||||
let g:sent_responses = []
|
||||
let g:unregistered_capabilities = []
|
||||
|
||||
function! ale#lsp#SendResponse(conn_id, id, result) abort
|
||||
call add(g:sent_responses, [a:conn_id, a:id, a:result])
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#UnregisterCapabilities(conn_id, unregisterations) abort
|
||||
call add(g:unregistered_capabilities, [a:conn_id, a:unregisterations])
|
||||
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
call ale#lsp_linter#SetLSPLinterMap({'1': {'name': 'expert', 'aliases': [], 'lsp': 'stdio'}})
|
||||
call ale#lsp_linter#SetDiagnosticURIMap({'14': 'file://foo.py'})
|
||||
|
||||
call ale#lsp_linter#HandleLSPResponse(1, {
|
||||
\ 'jsonrpc': '2.0',
|
||||
\ 'id': 14,
|
||||
\ 'method': 'client/unregisterCapability',
|
||||
\ 'params': {
|
||||
\ 'unregisterations': [
|
||||
\ {
|
||||
\ 'id': 'abc',
|
||||
\ 'method': 'textDocument/diagnostic',
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\})
|
||||
|
||||
AssertEqual
|
||||
\ [[1, 14, v:null]],
|
||||
\ g:sent_responses
|
||||
AssertEqual
|
||||
\ [[1, [{'id': 'abc', 'method': 'textDocument/diagnostic'}]]],
|
||||
\ g:unregistered_capabilities
|
||||
AssertEqual {'14': 'file://foo.py'}, ale#lsp_linter#GetDiagnosticURIMap()
|
||||
|
||||
unlet! g:sent_responses
|
||||
unlet! g:unregistered_capabilities
|
||||
runtime autoload/ale/lsp.vim
|
||||
|
||||
Execute(LSP errors should be logged in the history):
|
||||
|
||||
Reference in New Issue
Block a user