From 6ab3fdc4d0566c09e9456c3bf1b7aa92747fd0aa Mon Sep 17 00:00:00 2001 From: w0rp Date: Fri, 27 Apr 2018 22:52:11 +0100 Subject: [PATCH] Close #1521 - Allow the language to be set with simple strings for LSP linters --- ale_linters/dart/language_server.vim | 7 +---- ale_linters/glsl/glslls.vim | 6 +---- ale_linters/php/langserver.vim | 6 +---- ale_linters/python/pyls.vim | 6 +---- ale_linters/rust/rls.vim | 6 +---- ale_linters/typescript/tsserver.vim | 6 +---- autoload/ale/linter.vim | 26 ++++++++++++++++--- doc/ale.txt | 17 ++++++++---- .../test_php_langserver_callbacks.vader | 3 --- .../test_rust_rls_callbacks.vader | 3 --- test/test_linter_defintion_processing.vader | 24 +++++++++++++++++ 11 files changed, 65 insertions(+), 45 deletions(-) diff --git a/ale_linters/dart/language_server.vim b/ale_linters/dart/language_server.vim index 15c7701..bed77c5 100644 --- a/ale_linters/dart/language_server.vim +++ b/ale_linters/dart/language_server.vim @@ -7,10 +7,6 @@ function! ale_linters#dart#language_server#GetExecutable(buffer) abort return ale#Var(a:buffer, 'dart_language_server_executable') endfunction -function! ale_linters#dart#language_server#GetLanguage(buffer) abort - return 'dart' -endfunction - function! ale_linters#dart#language_server#GetProjectRoot(buffer) abort " Note: pub only looks for pubspec.yaml, there's no point in adding " support for pubspec.yml @@ -24,7 +20,6 @@ call ale#linter#Define('dart', { \ 'lsp': 'stdio', \ 'executable_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', \}) - diff --git a/ale_linters/glsl/glslls.vim b/ale_linters/glsl/glslls.vim index 67ea379..c19f28c 100644 --- a/ale_linters/glsl/glslls.vim +++ b/ale_linters/glsl/glslls.vim @@ -18,10 +18,6 @@ function! ale_linters#glsl#glslls#GetCommand(buffer) abort return ale#Escape(l:executable) . l:logfile_args . ' --stdin' endfunction -function! ale_linters#glsl#glslls#GetLanguage(buffer) abort - return 'glsl' -endfunction - function! ale_linters#glsl#glslls#GetProjectRoot(buffer) abort let l:project_root = ale#c#FindProjectRoot(a:buffer) @@ -33,6 +29,6 @@ call ale#linter#Define('glsl', { \ 'lsp': 'stdio', \ 'executable_callback': 'ale_linters#glsl#glslls#GetExecutable', \ 'command_callback': 'ale_linters#glsl#glslls#GetCommand', -\ 'language_callback': 'ale_linters#glsl#glslls#GetLanguage', +\ 'language': 'glsl', \ 'project_root_callback': 'ale_linters#glsl#glslls#GetProjectRoot', \}) diff --git a/ale_linters/php/langserver.vim b/ale_linters/php/langserver.vim index 7e1321f..0f3ead6 100644 --- a/ale_linters/php/langserver.vim +++ b/ale_linters/php/langserver.vim @@ -14,10 +14,6 @@ function! ale_linters#php#langserver#GetCommand(buffer) abort return 'php ' . ale#Escape(ale_linters#php#langserver#GetExecutable(a:buffer)) endfunction -function! ale_linters#php#langserver#GetLanguage(buffer) abort - return 'php' -endfunction - function! ale_linters#php#langserver#GetProjectRoot(buffer) abort let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git') @@ -29,6 +25,6 @@ call ale#linter#Define('php', { \ 'lsp': 'stdio', \ 'executable_callback': 'ale_linters#php#langserver#GetExecutable', \ 'command_callback': 'ale_linters#php#langserver#GetCommand', -\ 'language_callback': 'ale_linters#php#langserver#GetLanguage', +\ 'language': 'php', \ 'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot', \}) diff --git a/ale_linters/python/pyls.vim b/ale_linters/python/pyls.vim index 09f31ec..883b38f 100644 --- a/ale_linters/python/pyls.vim +++ b/ale_linters/python/pyls.vim @@ -14,16 +14,12 @@ function! ale_linters#python#pyls#GetCommand(buffer) abort return ale#Escape(l:executable) endfunction -function! ale_linters#python#pyls#GetLanguage(buffer) abort - return 'python' -endfunction - call ale#linter#Define('python', { \ 'name': 'pyls', \ 'lsp': 'stdio', \ 'executable_callback': 'ale_linters#python#pyls#GetExecutable', \ 'command_callback': 'ale_linters#python#pyls#GetCommand', -\ 'language_callback': 'ale_linters#python#pyls#GetLanguage', +\ 'language': 'python', \ 'project_root_callback': 'ale#python#FindProjectRoot', \ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \}) diff --git a/ale_linters/rust/rls.vim b/ale_linters/rust/rls.vim index 24316b0..d5160b1 100644 --- a/ale_linters/rust/rls.vim +++ b/ale_linters/rust/rls.vim @@ -19,10 +19,6 @@ function! ale_linters#rust#rls#GetCommand(buffer) abort endif endfunction -function! ale_linters#rust#rls#GetLanguage(buffer) abort - return 'rust' -endfunction - function! ale_linters#rust#rls#GetProjectRoot(buffer) abort let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml') @@ -34,6 +30,6 @@ call ale#linter#Define('rust', { \ 'lsp': 'stdio', \ 'executable_callback': 'ale_linters#rust#rls#GetExecutable', \ 'command_callback': 'ale_linters#rust#rls#GetCommand', -\ 'language_callback': 'ale_linters#rust#rls#GetLanguage', +\ 'language': 'rust', \ 'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot', \}) diff --git a/ale_linters/typescript/tsserver.vim b/ale_linters/typescript/tsserver.vim index 5eb77da..08bd0f4 100644 --- a/ale_linters/typescript/tsserver.vim +++ b/ale_linters/typescript/tsserver.vim @@ -10,10 +10,6 @@ function! ale_linters#typescript#tsserver#GetProjectRoot(buffer) abort return '' endfunction -function! ale_linters#typescript#tsserver#GetLanguage(buffer) abort - return '' -endfunction - function! ale_linters#typescript#tsserver#GetExecutable(buffer) abort return ale#node#FindExecutable(a:buffer, 'typescript_tsserver', [ \ 'node_modules/.bin/tsserver', @@ -26,5 +22,5 @@ call ale#linter#Define('typescript', { \ 'executable_callback': 'ale_linters#typescript#tsserver#GetExecutable', \ 'command_callback': 'ale_linters#typescript#tsserver#GetExecutable', \ 'project_root_callback': 'ale_linters#typescript#tsserver#GetProjectRoot', -\ 'language_callback': 'ale_linters#typescript#tsserver#GetLanguage', +\ 'language': '', \}) diff --git a/autoload/ale/linter.vim b/autoload/ale/linter.vim index 8aec259..1e0ec30 100644 --- a/autoload/ale/linter.vim +++ b/autoload/ale/linter.vim @@ -51,6 +51,10 @@ function! s:IsBoolean(value) abort return type(a:value) == type(0) && (a:value == 0 || a:value == 1) endfunction +function! s:LanguageGetter(buffer) dict abort + return l:self.language +endfunction + function! ale#linter#PreProcess(linter) abort if type(a:linter) != type({}) throw 'The linter object must be a Dictionary' @@ -185,10 +189,26 @@ function! ale#linter#PreProcess(linter) abort endif 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) - throw '`language_callback` must be a callback for LSP linters' + let l:obj.language = get(a:linter, 'language') + + 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 let l:obj.project_root_callback = get(a:linter, 'project_root_callback') diff --git a/doc/ale.txt b/doc/ale.txt index de6507e..ca15048 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2272,9 +2272,9 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()* process for a language server runnning, and communicates with it directly via a |channel|. - When this argument is not empty, then the - `project_callback` and `language_callback` arguments - must also be defined. + When this argument is not empty, `project_callback` + must be defined, and only one of either `language` or + `language_callback` must be defined. LSP linters handle diagnostics automatically, so 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 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 accepting a buffer number. A |String| should be returned representing the name of the language being checked. - This argument must only be set if the `lsp` argument - is also set to a non-empty string. + This option can be used instead of `language` if a + linter can check multiple languages. `aliases` A |List| of aliases for the linter name. diff --git a/test/command_callback/test_php_langserver_callbacks.vader b/test/command_callback/test_php_langserver_callbacks.vader index 0dc3063..ebcae0e 100644 --- a/test/command_callback/test_php_langserver_callbacks.vader +++ b/test/command_callback/test_php_langserver_callbacks.vader @@ -42,9 +42,6 @@ Execute(Vendor executables should be detected): \ )), \ 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): call ale#test#SetFilename('php-langserver-project/test.php') call mkdir(g:dir . '/.git') diff --git a/test/command_callback/test_rust_rls_callbacks.vader b/test/command_callback/test_rust_rls_callbacks.vader index d537bcc..16bde98 100644 --- a/test/command_callback/test_rust_rls_callbacks.vader +++ b/test/command_callback/test_rust_rls_callbacks.vader @@ -35,9 +35,6 @@ Execute(The toolchain should be ommitted if not given): \ ale#Escape('rls'), \ 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): AssertEqual '', ale_linters#rust#rls#GetProjectRoot(bufnr('')) diff --git a/test/test_linter_defintion_processing.vader b/test/test_linter_defintion_processing.vader index d946a60..653587b 100644 --- a/test/test_linter_defintion_processing.vader +++ b/test/test_linter_defintion_processing.vader @@ -421,6 +421,30 @@ Execute(PreProcess should accept LSP server configurations): 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): let g:linter = { \ 'name': 'x',