Close #1521 - Allow the language to be set with simple strings for LSP linters

This commit is contained in:
w0rp 2018-04-27 22:52:11 +01:00
parent d1d705cc84
commit 6ab3fdc4d0
No known key found for this signature in database
GPG Key ID: 0FC1ECAA8C81CD83
11 changed files with 65 additions and 45 deletions

View File

@ -7,10 +7,6 @@ function! ale_linters#dart#language_server#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'dart_language_server_executable') return ale#Var(a:buffer, 'dart_language_server_executable')
endfunction endfunction
function! ale_linters#dart#language_server#GetLanguage(buffer) abort
return 'dart'
endfunction
function! ale_linters#dart#language_server#GetProjectRoot(buffer) abort function! ale_linters#dart#language_server#GetProjectRoot(buffer) abort
" Note: pub only looks for pubspec.yaml, there's no point in adding " Note: pub only looks for pubspec.yaml, there's no point in adding
" support for pubspec.yml " support for pubspec.yml
@ -24,7 +20,6 @@ call ale#linter#Define('dart', {
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#dart#language_server#GetExecutable', \ 'executable_callback': 'ale_linters#dart#language_server#GetExecutable',
\ 'command_callback': 'ale_linters#dart#language_server#GetExecutable', \ 'command_callback': 'ale_linters#dart#language_server#GetExecutable',
\ 'language_callback': 'ale_linters#dart#language_server#GetLanguage', \ 'language': 'dart',
\ 'project_root_callback': 'ale_linters#dart#language_server#GetProjectRoot', \ 'project_root_callback': 'ale_linters#dart#language_server#GetProjectRoot',
\}) \})

View File

@ -18,10 +18,6 @@ function! ale_linters#glsl#glslls#GetCommand(buffer) abort
return ale#Escape(l:executable) . l:logfile_args . ' --stdin' return ale#Escape(l:executable) . l:logfile_args . ' --stdin'
endfunction endfunction
function! ale_linters#glsl#glslls#GetLanguage(buffer) abort
return 'glsl'
endfunction
function! ale_linters#glsl#glslls#GetProjectRoot(buffer) abort function! ale_linters#glsl#glslls#GetProjectRoot(buffer) abort
let l:project_root = ale#c#FindProjectRoot(a:buffer) let l:project_root = ale#c#FindProjectRoot(a:buffer)
@ -33,6 +29,6 @@ call ale#linter#Define('glsl', {
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#glsl#glslls#GetExecutable', \ 'executable_callback': 'ale_linters#glsl#glslls#GetExecutable',
\ 'command_callback': 'ale_linters#glsl#glslls#GetCommand', \ 'command_callback': 'ale_linters#glsl#glslls#GetCommand',
\ 'language_callback': 'ale_linters#glsl#glslls#GetLanguage', \ 'language': 'glsl',
\ 'project_root_callback': 'ale_linters#glsl#glslls#GetProjectRoot', \ 'project_root_callback': 'ale_linters#glsl#glslls#GetProjectRoot',
\}) \})

View File

@ -14,10 +14,6 @@ function! ale_linters#php#langserver#GetCommand(buffer) abort
return 'php ' . ale#Escape(ale_linters#php#langserver#GetExecutable(a:buffer)) return 'php ' . ale#Escape(ale_linters#php#langserver#GetExecutable(a:buffer))
endfunction endfunction
function! ale_linters#php#langserver#GetLanguage(buffer) abort
return 'php'
endfunction
function! ale_linters#php#langserver#GetProjectRoot(buffer) abort function! ale_linters#php#langserver#GetProjectRoot(buffer) abort
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git') let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
@ -29,6 +25,6 @@ call ale#linter#Define('php', {
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#php#langserver#GetExecutable', \ 'executable_callback': 'ale_linters#php#langserver#GetExecutable',
\ 'command_callback': 'ale_linters#php#langserver#GetCommand', \ 'command_callback': 'ale_linters#php#langserver#GetCommand',
\ 'language_callback': 'ale_linters#php#langserver#GetLanguage', \ 'language': 'php',
\ 'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot', \ 'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot',
\}) \})

View File

@ -14,16 +14,12 @@ function! ale_linters#python#pyls#GetCommand(buffer) abort
return ale#Escape(l:executable) return ale#Escape(l:executable)
endfunction endfunction
function! ale_linters#python#pyls#GetLanguage(buffer) abort
return 'python'
endfunction
call ale#linter#Define('python', { call ale#linter#Define('python', {
\ 'name': 'pyls', \ 'name': 'pyls',
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#python#pyls#GetExecutable', \ 'executable_callback': 'ale_linters#python#pyls#GetExecutable',
\ 'command_callback': 'ale_linters#python#pyls#GetCommand', \ 'command_callback': 'ale_linters#python#pyls#GetCommand',
\ 'language_callback': 'ale_linters#python#pyls#GetLanguage', \ 'language': 'python',
\ 'project_root_callback': 'ale#python#FindProjectRoot', \ 'project_root_callback': 'ale#python#FindProjectRoot',
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\}) \})

View File

@ -19,10 +19,6 @@ function! ale_linters#rust#rls#GetCommand(buffer) abort
endif endif
endfunction endfunction
function! ale_linters#rust#rls#GetLanguage(buffer) abort
return 'rust'
endfunction
function! ale_linters#rust#rls#GetProjectRoot(buffer) abort function! ale_linters#rust#rls#GetProjectRoot(buffer) abort
let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml') let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml')
@ -34,6 +30,6 @@ call ale#linter#Define('rust', {
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#rust#rls#GetExecutable', \ 'executable_callback': 'ale_linters#rust#rls#GetExecutable',
\ 'command_callback': 'ale_linters#rust#rls#GetCommand', \ 'command_callback': 'ale_linters#rust#rls#GetCommand',
\ 'language_callback': 'ale_linters#rust#rls#GetLanguage', \ 'language': 'rust',
\ 'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot', \ 'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot',
\}) \})

View File

@ -10,10 +10,6 @@ function! ale_linters#typescript#tsserver#GetProjectRoot(buffer) abort
return '' return ''
endfunction endfunction
function! ale_linters#typescript#tsserver#GetLanguage(buffer) abort
return ''
endfunction
function! ale_linters#typescript#tsserver#GetExecutable(buffer) abort function! ale_linters#typescript#tsserver#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'typescript_tsserver', [ return ale#node#FindExecutable(a:buffer, 'typescript_tsserver', [
\ 'node_modules/.bin/tsserver', \ 'node_modules/.bin/tsserver',
@ -26,5 +22,5 @@ call ale#linter#Define('typescript', {
\ 'executable_callback': 'ale_linters#typescript#tsserver#GetExecutable', \ 'executable_callback': 'ale_linters#typescript#tsserver#GetExecutable',
\ 'command_callback': 'ale_linters#typescript#tsserver#GetExecutable', \ 'command_callback': 'ale_linters#typescript#tsserver#GetExecutable',
\ 'project_root_callback': 'ale_linters#typescript#tsserver#GetProjectRoot', \ 'project_root_callback': 'ale_linters#typescript#tsserver#GetProjectRoot',
\ 'language_callback': 'ale_linters#typescript#tsserver#GetLanguage', \ 'language': '',
\}) \})

View File

@ -51,6 +51,10 @@ function! s:IsBoolean(value) abort
return type(a:value) == type(0) && (a:value == 0 || a:value == 1) return type(a:value) == type(0) && (a:value == 0 || a:value == 1)
endfunction endfunction
function! s:LanguageGetter(buffer) dict abort
return l:self.language
endfunction
function! ale#linter#PreProcess(linter) abort function! ale#linter#PreProcess(linter) abort
if type(a:linter) != type({}) if type(a:linter) != type({})
throw 'The linter object must be a Dictionary' throw 'The linter object must be a Dictionary'
@ -185,10 +189,26 @@ function! ale#linter#PreProcess(linter) abort
endif endif
if l:needs_lsp_details if l:needs_lsp_details
let l:obj.language_callback = get(a:linter, 'language_callback') if has_key(a:linter, 'language')
if has_key(a:linter, 'language_callback')
throw 'Only one of `language` or `language_callback` '
\ . 'should be set'
endif
if !s:IsCallback(l:obj.language_callback) let l:obj.language = get(a:linter, 'language')
throw '`language_callback` must be a callback for LSP linters'
if type(l:obj.language) != type('')
throw '`language` must be a string'
endif
" Make 'language_callback' return the 'language' value.
let l:obj.language_callback = function('s:LanguageGetter')
else
let l:obj.language_callback = get(a:linter, 'language_callback')
if !s:IsCallback(l:obj.language_callback)
throw '`language_callback` must be a callback for LSP linters'
endif
endif endif
let l:obj.project_root_callback = get(a:linter, 'project_root_callback') let l:obj.project_root_callback = get(a:linter, 'project_root_callback')

View File

@ -2272,9 +2272,9 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
process for a language server runnning, and process for a language server runnning, and
communicates with it directly via a |channel|. communicates with it directly via a |channel|.
When this argument is not empty, then the When this argument is not empty, `project_callback`
`project_callback` and `language_callback` arguments must be defined, and only one of either `language` or
must also be defined. `language_callback` must be defined.
LSP linters handle diagnostics automatically, so LSP linters handle diagnostics automatically, so
the `callback` argument must not be defined. the `callback` argument must not be defined.
@ -2289,13 +2289,20 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
This argument must only be set if the `lsp` argument This argument must only be set if the `lsp` argument
is also set to a non-empty string. is also set to a non-empty string.
`language` A |String| representing the name of the language
being checked. This string will be sent to the LSP to
tell it what type of language is being checked.
This argument must only be set if the `lsp` argument
is also set to a non-empty string.
`language_callback` A |String| or |Funcref| for a callback function `language_callback` A |String| or |Funcref| for a callback function
accepting a buffer number. A |String| should be accepting a buffer number. A |String| should be
returned representing the name of the language being returned representing the name of the language being
checked. checked.
This argument must only be set if the `lsp` argument This option can be used instead of `language` if a
is also set to a non-empty string. linter can check multiple languages.
`aliases` A |List| of aliases for the linter name. `aliases` A |List| of aliases for the linter name.

View File

@ -42,9 +42,6 @@ Execute(Vendor executables should be detected):
\ )), \ )),
\ ale_linters#php#langserver#GetCommand(bufnr('')) \ ale_linters#php#langserver#GetCommand(bufnr(''))
Execute(The language string should be correct):
AssertEqual 'php', ale_linters#php#langserver#GetLanguage(bufnr(''))
Execute(The project path should be correct for .git directories): Execute(The project path should be correct for .git directories):
call ale#test#SetFilename('php-langserver-project/test.php') call ale#test#SetFilename('php-langserver-project/test.php')
call mkdir(g:dir . '/.git') call mkdir(g:dir . '/.git')

View File

@ -35,9 +35,6 @@ Execute(The toolchain should be ommitted if not given):
\ ale#Escape('rls'), \ ale#Escape('rls'),
\ ale_linters#rust#rls#GetCommand(bufnr('')) \ ale_linters#rust#rls#GetCommand(bufnr(''))
Execute(The language string should be correct):
AssertEqual 'rust', ale_linters#rust#rls#GetLanguage(bufnr(''))
Execute(The project root should be detected correctly): Execute(The project root should be detected correctly):
AssertEqual '', ale_linters#rust#rls#GetProjectRoot(bufnr('')) AssertEqual '', ale_linters#rust#rls#GetProjectRoot(bufnr(''))

View File

@ -421,6 +421,30 @@ Execute(PreProcess should accept LSP server configurations):
AssertEqual 'socket', ale#linter#PreProcess(g:linter).lsp AssertEqual 'socket', ale#linter#PreProcess(g:linter).lsp
Execute(PreProcess should accept let you specify the language as just a string):
let g:linter = {
\ 'name': 'x',
\ 'lsp': 'socket',
\ 'address_callback': 'X',
\ 'language': 'foobar',
\ 'project_root_callback': 'x',
\}
AssertEqual 'foobar', ale#linter#PreProcess(g:linter).language_callback(0)
Execute(PreProcess should complain about using language and language_callback together):
let g:linter = {
\ 'name': 'x',
\ 'lsp': 'socket',
\ 'address_callback': 'X',
\ 'language': 'x',
\ 'language_callback': 'x',
\ 'project_root_callback': 'x',
\}
AssertThrows call ale#linter#PreProcess(g:linter)
AssertEqual 'Only one of `language` or `language_callback` should be set', g:vader_exception
Execute(PreProcess should require an address_callback for LSP socket configurations): Execute(PreProcess should require an address_callback for LSP socket configurations):
let g:linter = { let g:linter = {
\ 'name': 'x', \ 'name': 'x',