mirror of
https://github.com/dense-analysis/ale.git
synced 2026-05-17 13:59:47 +08:00
307f2b99ff
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.
346 lines
9.0 KiB
Plaintext
346 lines
9.0 KiB
Plaintext
Before:
|
|
runtime autoload/ale/lsp.vim
|
|
|
|
let g:message_list = []
|
|
|
|
" Register a fake connection and get it for tests.
|
|
call ale#lsp#Register('ale-fake-lsp-server', '/code', '', {})
|
|
let b:conn = ale#lsp#GetConnections()['ale-fake-lsp-server:/code']
|
|
|
|
function! ale#lsp#Send(conn_id, message) abort
|
|
call add(g:message_list, a:message)
|
|
|
|
return 42
|
|
endfunction
|
|
|
|
After:
|
|
" Remove the connection with the ID.
|
|
call ale#lsp#RemoveConnectionWithID(b:conn.id)
|
|
|
|
unlet! b:conn
|
|
unlet! g:message_list
|
|
|
|
runtime autoload/ale/lsp.vim
|
|
|
|
Execute(Messages with no method and capabilities should initialize projects):
|
|
call ale#lsp#HandleInitResponse(b:conn, {
|
|
\ 'result': {'capabilities': {}},
|
|
\})
|
|
|
|
AssertEqual 1, b:conn.initialized
|
|
AssertEqual [[1, 'initialized', {}]], g:message_list
|
|
|
|
Execute(Other messages should not initialize projects):
|
|
call ale#lsp#HandleInitResponse(b:conn, {'method': 'lolwat'})
|
|
|
|
AssertEqual 0, b:conn.initialized
|
|
AssertEqual [], g:message_list
|
|
|
|
call ale#lsp#HandleInitResponse(b:conn, {'result': {'x': {}}})
|
|
|
|
AssertEqual 0, b:conn.initialized
|
|
AssertEqual [], g:message_list
|
|
|
|
Execute(Capabilities should be set up correctly):
|
|
call ale#lsp#HandleInitResponse(b:conn, {
|
|
\ 'jsonrpc': '2.0',
|
|
\ 'id': 1,
|
|
\ 'result': {
|
|
\ 'capabilities': {
|
|
\ 'renameProvider': v:true,
|
|
\ 'executeCommandProvider': {
|
|
\ 'commands': [],
|
|
\ },
|
|
\ 'hoverProvider': v:true,
|
|
\ 'documentSymbolProvider': v:true,
|
|
\ 'documentRangeFormattingProvider': v:true,
|
|
\ 'codeLensProvider': {
|
|
\ 'resolveProvider': v:false
|
|
\ },
|
|
\ 'referencesProvider': v:true,
|
|
\ 'textDocumentSync': 2,
|
|
\ 'documentFormattingProvider': v:true,
|
|
\ 'codeActionProvider': v:true,
|
|
\ 'signatureHelpProvider': {
|
|
\ 'triggerCharacters': ['(', ','],
|
|
\ },
|
|
\ 'completionProvider': {
|
|
\ 'triggerCharacters': ['.'],
|
|
\ 'resolveProvider': v:false
|
|
\ },
|
|
\ 'definitionProvider': v:true,
|
|
\ 'experimental': {},
|
|
\ 'documentHighlightProvider': v:true,
|
|
\ 'workspaceSymbolProvider': v:true
|
|
\ },
|
|
\ },
|
|
\})
|
|
|
|
AssertEqual 1, b:conn.initialized
|
|
AssertEqual
|
|
\ {
|
|
\ 'code_actions': 1,
|
|
\ 'completion': 1,
|
|
\ 'completion_trigger_characters': ['.'],
|
|
\ 'definition': 1,
|
|
\ 'did_save': 0,
|
|
\ 'filerename': 0,
|
|
\ 'hover': 1,
|
|
\ 'implementation': 0,
|
|
\ 'includeText': 0,
|
|
\ 'references': 1,
|
|
\ 'rename': 1,
|
|
\ 'pull_model': 0,
|
|
\ 'symbol_search': 1,
|
|
\ 'typeDefinition': 0,
|
|
\ },
|
|
\ b:conn.capabilities
|
|
AssertEqual [[1, 'initialized', {}]], g:message_list
|
|
|
|
Execute(Disabled capabilities should be recognised correctly):
|
|
call ale#lsp#HandleInitResponse(b:conn, {
|
|
\ 'jsonrpc': '2.0',
|
|
\ 'id': 1,
|
|
\ 'result': {
|
|
\ 'capabilities': {
|
|
\ 'renameProvider': v:false,
|
|
\ 'executeCommandProvider': {
|
|
\ 'commands': [],
|
|
\ },
|
|
\ 'hoverProvider': v:false,
|
|
\ 'documentSymbolProvider': v:true,
|
|
\ 'documentRangeFormattingProvider': v:true,
|
|
\ 'codeLensProvider': {
|
|
\ 'resolveProvider': v:false
|
|
\ },
|
|
\ 'referencesProvider': v:false,
|
|
\ 'textDocumentSync': 2,
|
|
\ 'documentFormattingProvider': v:true,
|
|
\ 'codeActionProvider': v:false,
|
|
\ 'signatureHelpProvider': {
|
|
\ 'triggerCharacters': ['(', ','],
|
|
\ },
|
|
\ 'definitionProvider': v:false,
|
|
\ 'experimental': {},
|
|
\ 'documentHighlightProvider': v:true,
|
|
\ 'diagnosticProvider': {},
|
|
\ },
|
|
\ },
|
|
\})
|
|
|
|
AssertEqual 1, b:conn.initialized
|
|
AssertEqual
|
|
\ {
|
|
\ 'code_actions': 0,
|
|
\ 'completion': 0,
|
|
\ 'completion_trigger_characters': [],
|
|
\ 'definition': 0,
|
|
\ 'did_save': 0,
|
|
\ 'filerename': 0,
|
|
\ 'hover': 0,
|
|
\ 'implementation': 0,
|
|
\ 'includeText': 0,
|
|
\ 'references': 0,
|
|
\ 'rename': 0,
|
|
\ 'pull_model': 0,
|
|
\ 'symbol_search': 0,
|
|
\ 'typeDefinition': 0,
|
|
\ },
|
|
\ b:conn.capabilities
|
|
AssertEqual [[1, 'initialized', {}]], g:message_list
|
|
|
|
Execute(Capabilities should be enabled when sent as Dictionaries):
|
|
call ale#lsp#HandleInitResponse(b:conn, {
|
|
\ 'jsonrpc': '2.0',
|
|
\ 'id': 1,
|
|
\ 'result': {
|
|
\ 'capabilities': {
|
|
\ 'renameProvider': {},
|
|
\ 'executeCommandProvider': {
|
|
\ 'commands': [],
|
|
\ },
|
|
\ 'hoverProvider': {},
|
|
\ 'documentSymbolProvider': v:true,
|
|
\ 'documentRangeFormattingProvider': v:true,
|
|
\ 'codeLensProvider': {
|
|
\ 'resolveProvider': v:false
|
|
\ },
|
|
\ 'completionProvider': {
|
|
\ 'triggerCharacters': ['.'],
|
|
\ 'resolveProvider': v:false
|
|
\ },
|
|
\ 'referencesProvider': {},
|
|
\ 'textDocumentSync': {
|
|
\ 'save': {
|
|
\ 'includeText': v:true
|
|
\ }
|
|
\ },
|
|
\ 'documentFormattingProvider': v:true,
|
|
\ 'codeActionProvider': v:true,
|
|
\ 'signatureHelpProvider': {
|
|
\ 'triggerCharacters': ['(', ','],
|
|
\ },
|
|
\ 'definitionProvider': {},
|
|
\ 'typeDefinitionProvider': {},
|
|
\ 'implementationProvider': {},
|
|
\ 'experimental': {},
|
|
\ 'documentHighlightProvider': v:true,
|
|
\ 'diagnosticProvider': {
|
|
\ 'interFileDependencies': v:false,
|
|
\ },
|
|
\ 'workspaceSymbolProvider': {}
|
|
\ },
|
|
\ },
|
|
\})
|
|
|
|
AssertEqual 1, b:conn.initialized
|
|
AssertEqual
|
|
\ {
|
|
\ 'code_actions': 1,
|
|
\ 'completion': 1,
|
|
\ 'completion_trigger_characters': ['.'],
|
|
\ 'definition': 1,
|
|
\ 'did_save': 1,
|
|
\ 'filerename': 0,
|
|
\ 'hover': 1,
|
|
\ 'implementation': 1,
|
|
\ 'includeText': 1,
|
|
\ 'references': 1,
|
|
\ 'rename': 1,
|
|
\ 'pull_model': 1,
|
|
\ 'symbol_search': 1,
|
|
\ 'typeDefinition': 1,
|
|
\ },
|
|
\ b:conn.capabilities
|
|
AssertEqual [[1, 'initialized', {}]], g:message_list
|
|
|
|
Execute(Pull model diagnostics should be enabled when registered dynamically):
|
|
AssertEqual 0, b:conn.capabilities.pull_model
|
|
|
|
AssertEqual
|
|
\ 1,
|
|
\ ale#lsp#RegisterCapabilities(b:conn.id, [
|
|
\ {
|
|
\ 'id': 'pyright-diagnostics',
|
|
\ 'method': 'textDocument/diagnostic',
|
|
\ 'registerOptions': {
|
|
\ 'interFileDependencies': v:true,
|
|
\ 'workspaceDiagnostics': v:false,
|
|
\ 'documentSelector': v:null,
|
|
\ 'identifier': 'Pyright',
|
|
\ },
|
|
\ },
|
|
\ ])
|
|
|
|
AssertEqual 1, b:conn.capabilities.pull_model
|
|
|
|
Execute(Pull model diagnostics should be disabled when unregistered dynamically):
|
|
call ale#lsp#RegisterCapabilities(b:conn.id, [
|
|
\ {
|
|
\ 'id': 'pyright-diagnostics',
|
|
\ 'method': 'textDocument/diagnostic',
|
|
\ 'registerOptions': {
|
|
\ 'interFileDependencies': v:true,
|
|
\ },
|
|
\ },
|
|
\ ])
|
|
|
|
AssertEqual 1, b:conn.capabilities.pull_model
|
|
|
|
AssertEqual
|
|
\ 1,
|
|
\ ale#lsp#UnregisterCapabilities(b:conn.id, [
|
|
\ {
|
|
\ 'id': 'pyright-diagnostics',
|
|
\ 'method': 'textDocument/diagnostic',
|
|
\ },
|
|
\ ])
|
|
|
|
AssertEqual 0, b:conn.capabilities.pull_model
|
|
|
|
Execute(Pull model diagnostics should stay enabled while another registration exists):
|
|
call ale#lsp#RegisterCapabilities(b:conn.id, [
|
|
\ {
|
|
\ 'id': 'pyright-diagnostics-one',
|
|
\ 'method': 'textDocument/diagnostic',
|
|
\ 'registerOptions': {
|
|
\ 'interFileDependencies': v:true,
|
|
\ },
|
|
\ },
|
|
\ {
|
|
\ 'id': 'pyright-diagnostics-two',
|
|
\ 'method': 'textDocument/diagnostic',
|
|
\ 'registerOptions': {
|
|
\ 'interFileDependencies': v:true,
|
|
\ },
|
|
\ },
|
|
\ ])
|
|
|
|
call ale#lsp#UnregisterCapabilities(b:conn.id, [
|
|
\ {
|
|
\ 'id': 'pyright-diagnostics-one',
|
|
\ 'method': 'textDocument/diagnostic',
|
|
\ },
|
|
\ ])
|
|
|
|
AssertEqual 1, b:conn.capabilities.pull_model
|
|
|
|
Execute(Unregistering non-diagnostic registrations should not change diagnostics):
|
|
call ale#lsp#RegisterCapabilities(b:conn.id, [
|
|
\ {
|
|
\ 'id': 'pyright-diagnostics',
|
|
\ 'method': 'textDocument/diagnostic',
|
|
\ 'registerOptions': {
|
|
\ 'interFileDependencies': v:true,
|
|
\ },
|
|
\ },
|
|
\ {
|
|
\ 'id': 'workspace-symbols',
|
|
\ 'method': 'workspace/symbol',
|
|
\ 'registerOptions': {},
|
|
\ },
|
|
\ ])
|
|
|
|
call ale#lsp#UnregisterCapabilities(b:conn.id, [
|
|
\ {
|
|
\ 'id': 'workspace-symbols',
|
|
\ 'method': 'workspace/symbol',
|
|
\ },
|
|
\ ])
|
|
|
|
AssertEqual 1, b:conn.capabilities.pull_model
|
|
|
|
Execute(Static pull model diagnostics should not be disabled by unregistering dynamic registrations):
|
|
call ale#lsp#UpdateCapabilities(b:conn.id, {
|
|
\ 'diagnosticProvider': {
|
|
\ 'interFileDependencies': v:false,
|
|
\ },
|
|
\})
|
|
|
|
call ale#lsp#RegisterCapabilities(b:conn.id, [
|
|
\ {
|
|
\ 'id': 'pyright-diagnostics',
|
|
\ 'method': 'textDocument/diagnostic',
|
|
\ 'registerOptions': {
|
|
\ 'interFileDependencies': v:true,
|
|
\ },
|
|
\ },
|
|
\ ])
|
|
|
|
call ale#lsp#UnregisterCapabilities(b:conn.id, [
|
|
\ {
|
|
\ 'id': 'pyright-diagnostics',
|
|
\ 'method': 'textDocument/diagnostic',
|
|
\ },
|
|
\ ])
|
|
|
|
AssertEqual 1, b:conn.capabilities.pull_model
|
|
|
|
Execute(Results that are not dictionaries should be handled correctly):
|
|
call ale#lsp#HandleInitResponse(b:conn, {
|
|
\ 'jsonrpc': '2.0',
|
|
\ 'id': 1,
|
|
\ 'result': v:null,
|
|
\})
|
|
AssertEqual [], g:message_list
|