mirror of https://github.com/dense-analysis/ale
Support an 'stdio' type for linter defintions, and require a command for LSP connections via programs
This commit is contained in:
parent
b731bd77ab
commit
857ca941d2
|
@ -19,5 +19,6 @@ call ale#linter#Define('typescript', {
|
|||
\ 'name': 'tsserver',
|
||||
\ 'lsp': 'tsserver',
|
||||
\ 'executable_callback': 'ale_linters#typescript#tsserver#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#typescript#tsserver#GetExecutable',
|
||||
\ 'callback': 'ale_linters#typescript#tsserver#Handle',
|
||||
\})
|
||||
|
|
|
@ -171,11 +171,10 @@ endfunction
|
|||
|
||||
function! s:GetCompletionsForTSServer(linter) abort
|
||||
let l:buffer = bufnr('')
|
||||
let l:executable = has_key(a:linter, 'executable_callback')
|
||||
\ ? ale#util#GetFunction(a:linter.executable_callback)(l:buffer)
|
||||
\ : a:linter.executable
|
||||
let l:command = ale#job#PrepareCommand(l:executable)
|
||||
|
||||
let l:executable = ale#linter#GetExecutable(l:buffer, a:linter)
|
||||
let l:command = ale#job#PrepareCommand(
|
||||
\ ale#linter#GetCommand(l:buffer, a:linter),
|
||||
\)
|
||||
let l:id = ale#lsp#StartProgram(
|
||||
\ l:executable,
|
||||
\ l:command,
|
||||
|
|
|
@ -502,11 +502,8 @@ function! ale#engine#ProcessChain(buffer, linter, chain_index, input) abort
|
|||
let l:input = []
|
||||
let l:chain_index += 1
|
||||
endwhile
|
||||
elseif has_key(a:linter, 'command_callback')
|
||||
" If there is a callback for generating a command, call that instead.
|
||||
let l:command = ale#util#GetFunction(a:linter.command_callback)(a:buffer)
|
||||
else
|
||||
let l:command = a:linter.command
|
||||
let l:command = ale#linter#GetCommand(a:buffer, a:linter)
|
||||
endif
|
||||
|
||||
if empty(l:command)
|
||||
|
@ -563,7 +560,9 @@ endfunction
|
|||
function! s:CheckWithTSServer(buffer, linter, executable) abort
|
||||
let l:info = g:ale_buffer_info[a:buffer]
|
||||
|
||||
let l:command = ale#job#PrepareCommand(a:executable)
|
||||
let l:command = ale#job#PrepareCommand(
|
||||
\ ale#linter#GetCommand(a:buffer, a:linter),
|
||||
\)
|
||||
let l:id = ale#lsp#StartProgram(
|
||||
\ a:executable,
|
||||
\ l:command,
|
||||
|
@ -598,9 +597,7 @@ endfunction
|
|||
|
||||
function! ale#engine#Invoke(buffer, linter) abort
|
||||
if empty(a:linter.lsp) || a:linter.lsp ==# 'tsserver'
|
||||
let l:executable = has_key(a:linter, 'executable_callback')
|
||||
\ ? ale#util#GetFunction(a:linter.executable_callback)(a:buffer)
|
||||
\ : a:linter.executable
|
||||
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter)
|
||||
|
||||
" Run this program if it can be executed.
|
||||
if s:IsExecutable(l:executable)
|
||||
|
|
|
@ -63,25 +63,18 @@ function! ale#linter#PreProcess(linter) abort
|
|||
throw '`callback` must be defined with a callback to accept output'
|
||||
endif
|
||||
|
||||
let l:needs_executable = 0
|
||||
let l:needs_address = 0
|
||||
let l:needs_command = 0
|
||||
let l:needs_address = l:obj.lsp ==# 'socket'
|
||||
let l:needs_executable = l:obj.lsp !=# 'socket'
|
||||
let l:needs_command = l:obj.lsp !=# 'socket'
|
||||
|
||||
if l:obj.lsp ==# 'tsserver'
|
||||
let l:needs_executable = 1
|
||||
elseif l:obj.lsp ==# 'lsp'
|
||||
let l:needs_address = 1
|
||||
elseif !empty(l:obj.lsp)
|
||||
if index(['', 'socket', 'stdio', 'tsserver'], l:obj.lsp) < 0
|
||||
throw '`lsp` must be either `''lsp''` or `''tsserver''` if defined'
|
||||
else
|
||||
let l:needs_executable = 1
|
||||
let l:needs_command = 1
|
||||
endif
|
||||
|
||||
if !l:needs_executable
|
||||
if has_key(a:linter, 'executable')
|
||||
\|| has_key(a:linter, 'executable_callback')
|
||||
throw '`executable` and `executable_callback` cannot be used when lsp == ''lsp'''
|
||||
throw '`executable` and `executable_callback` cannot be used when lsp == ''socket'''
|
||||
endif
|
||||
elseif has_key(a:linter, 'executable_callback')
|
||||
let l:obj.executable_callback = a:linter.executable_callback
|
||||
|
@ -103,7 +96,7 @@ function! ale#linter#PreProcess(linter) abort
|
|||
if has_key(a:linter, 'command')
|
||||
\|| has_key(a:linter, 'command_callback')
|
||||
\|| has_key(a:linter, 'command_chain')
|
||||
throw '`command` and `command_callback` and `command_chain` cannot be used when `lsp` is set'
|
||||
throw '`command` and `command_callback` and `command_chain` cannot be used when lsp == ''socket'''
|
||||
endif
|
||||
elseif has_key(a:linter, 'command_chain')
|
||||
let l:obj.command_chain = a:linter.command_chain
|
||||
|
@ -167,7 +160,7 @@ function! ale#linter#PreProcess(linter) abort
|
|||
|
||||
if !l:needs_address
|
||||
if has_key(a:linter, 'address_callback')
|
||||
throw '`address_callback` cannot be used when lsp != ''lsp'''
|
||||
throw '`address_callback` cannot be used when lsp != ''socket'''
|
||||
endif
|
||||
elseif has_key(a:linter, 'address_callback')
|
||||
let l:obj.address_callback = a:linter.address_callback
|
||||
|
@ -334,3 +327,18 @@ function! ale#linter#Get(original_filetypes) abort
|
|||
|
||||
return reverse(l:combined_linters)
|
||||
endfunction
|
||||
|
||||
" Given a buffer and linter, get the executable String for the linter.
|
||||
function! ale#linter#GetExecutable(buffer, linter) abort
|
||||
return has_key(a:linter, 'executable_callback')
|
||||
\ ? ale#util#GetFunction(a:linter.executable_callback)(a:buffer)
|
||||
\ : a:linter.executable
|
||||
endfunction
|
||||
|
||||
" Given a buffer and linter, get the command String for the linter.
|
||||
" The command_chain key is not supported.
|
||||
function! ale#linter#GetCommand(buffer, linter) abort
|
||||
return has_key(a:linter, 'command_callback')
|
||||
\ ? ale#util#GetFunction(a:linter.command_callback)(a:buffer)
|
||||
\ : a:linter.command
|
||||
endfunction
|
||||
|
|
|
@ -370,6 +370,7 @@ Execute(PreProcess should accept tsserver LSP configuration):
|
|||
let g:linter = {
|
||||
\ 'name': 'x',
|
||||
\ 'executable': 'x',
|
||||
\ 'command': 'x',
|
||||
\ 'lsp': 'tsserver',
|
||||
\ 'callback': 'x',
|
||||
\}
|
||||
|
@ -379,46 +380,48 @@ Execute(PreProcess should accept tsserver LSP configuration):
|
|||
call remove(g:linter, 'executable')
|
||||
let g:linter.executable_callback = 'X'
|
||||
|
||||
call ale#linter#PreProcess(g:linter).lsp
|
||||
|
||||
Execute(PreProcess should complain about commands being set for LSP configurations):
|
||||
let g:linter = {
|
||||
\ 'name': 'x',
|
||||
\ 'executable': 'x',
|
||||
\ 'lsp': 'tsserver',
|
||||
\ 'command': 'x',
|
||||
\ 'callback': 'x',
|
||||
\}
|
||||
|
||||
AssertThrows call ale#linter#PreProcess(g:linter)
|
||||
AssertEqual '`command` and `command_callback` and `command_chain` cannot be used when `lsp` is set', g:vader_exception
|
||||
call ale#linter#PreProcess(g:linter)
|
||||
|
||||
call remove(g:linter, 'command')
|
||||
let g:linter.command_callback = 'X'
|
||||
|
||||
AssertThrows call ale#linter#PreProcess(g:linter)
|
||||
AssertEqual '`command` and `command_callback` and `command_chain` cannot be used when `lsp` is set', g:vader_exception
|
||||
call ale#linter#PreProcess(g:linter)
|
||||
|
||||
call remove(g:linter, 'command_callback')
|
||||
let g:linter.command_chain = []
|
||||
Execute(PreProcess should accept stdio LSP configuration):
|
||||
let g:linter = {
|
||||
\ 'name': 'x',
|
||||
\ 'executable': 'x',
|
||||
\ 'command': 'x',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'callback': 'x',
|
||||
\}
|
||||
|
||||
AssertThrows call ale#linter#PreProcess(g:linter)
|
||||
AssertEqual '`command` and `command_callback` and `command_chain` cannot be used when `lsp` is set', g:vader_exception
|
||||
AssertEqual 'stdio', ale#linter#PreProcess(g:linter).lsp
|
||||
|
||||
call remove(g:linter, 'executable')
|
||||
let g:linter.executable_callback = 'X'
|
||||
|
||||
call ale#linter#PreProcess(g:linter)
|
||||
|
||||
call remove(g:linter, 'command')
|
||||
let g:linter.command_callback = 'X'
|
||||
|
||||
call ale#linter#PreProcess(g:linter)
|
||||
|
||||
Execute(PreProcess should accept LSP server configurations):
|
||||
let g:linter = {
|
||||
\ 'name': 'x',
|
||||
\ 'lsp': 'lsp',
|
||||
\ 'lsp': 'socket',
|
||||
\ 'callback': 'x',
|
||||
\ 'address_callback': 'X',
|
||||
\}
|
||||
|
||||
AssertEqual 'lsp', ale#linter#PreProcess(g:linter).lsp
|
||||
AssertEqual 'socket', ale#linter#PreProcess(g:linter).lsp
|
||||
|
||||
Execute(PreProcess should require an address_callback for LSP server configurations):
|
||||
Execute(PreProcess should require an address_callback for LSP socket configurations):
|
||||
let g:linter = {
|
||||
\ 'name': 'x',
|
||||
\ 'lsp': 'lsp',
|
||||
\ 'lsp': 'socket',
|
||||
\ 'callback': 'x',
|
||||
\}
|
||||
|
||||
|
@ -435,4 +438,4 @@ Execute(PreProcess should complain about address_callback for non-LSP linters):
|
|||
\}
|
||||
|
||||
AssertThrows call ale#linter#PreProcess(g:linter)
|
||||
AssertEqual '`address_callback` cannot be used when lsp != ''lsp''', g:vader_exception
|
||||
AssertEqual '`address_callback` cannot be used when lsp != ''socket''', g:vader_exception
|
||||
|
|
Loading…
Reference in New Issue