From 2c252c0f12868c5bbe9a00bd8bc37b32ae3802c4 Mon Sep 17 00:00:00 2001 From: w0rp Date: Sun, 30 Jul 2017 23:34:58 +0100 Subject: [PATCH] #517 - Get the Rust language server working in a basic way --- ale_linters/rust/langserver.vim | 33 +++++++++++++++++++++++++++++++++ autoload/ale/linter.vim | 6 ++++++ autoload/ale/lsp.vim | 10 ++++++++-- 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 ale_linters/rust/langserver.vim diff --git a/ale_linters/rust/langserver.vim b/ale_linters/rust/langserver.vim new file mode 100644 index 0000000..5e42a97 --- /dev/null +++ b/ale_linters/rust/langserver.vim @@ -0,0 +1,33 @@ +" Author: w0rp +" Description: A language server for Rust + +call ale#Set('rust_langserver_executable', 'rls') + +function! ale_linters#rust#langserver#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'rust_langserver_executable') +endfunction + +function! ale_linters#rust#langserver#GetCommand(buffer) abort + let l:executable = ale_linters#rust#langserver#GetExecutable(a:buffer) + + return ale#Escape(l:executable) . ' +nightly' +endfunction + +function! ale_linters#rust#langserver#GetLanguage(buffer) abort + return 'rust' +endfunction + +function! ale_linters#rust#langserver#GetProjectRoot(buffer) abort + let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml') + + return !empty(l:cargo_file) ? fnamemodify(l:cargo_file, ':h') : '' +endfunction + +call ale#linter#Define('rust', { +\ 'name': 'langserver', +\ 'lsp': 'stdio', +\ 'executable_callback': 'ale_linters#rust#langserver#GetExecutable', +\ 'command_callback': 'ale_linters#rust#langserver#GetCommand', +\ 'language_callback': 'ale_linters#rust#langserver#GetLanguage', +\ 'project_root_callback': 'ale_linters#rust#langserver#GetProjectRoot', +\}) diff --git a/autoload/ale/linter.vim b/autoload/ale/linter.vim index 0af42af..8fc6851 100644 --- a/autoload/ale/linter.vim +++ b/autoload/ale/linter.vim @@ -377,6 +377,12 @@ function! ale#linter#StartLSP(buffer, linter, callback) abort let l:address = '' let l:root = ale#util#GetFunction(a:linter.project_root_callback)(a:buffer) + if empty(l:root) && a:linter.lsp !=# 'tsserver' + " If there's no project root, then we can't check files with LSP, + " unless we are using tsserver, which doesn't use project roots. + return {} + endif + if a:linter.lsp ==# 'socket' let l:address = ale#linter#GetAddress(a:buffer, a:linter) let l:conn_id = ale#lsp#ConnectToAddress( diff --git a/autoload/ale/lsp.vim b/autoload/ale/lsp.vim index 855abb1..eb66eb4 100644 --- a/autoload/ale/lsp.vim +++ b/autoload/ale/lsp.vim @@ -190,7 +190,13 @@ function! ale#lsp#HandleOtherInitializeResponses(conn, response) abort return endif - if get(a:response, 'method', '') ==# 'textDocument/publishDiagnostics' + if get(a:response, 'method', '') ==# '' + if has_key(get(a:response, 'result', {}), 'capabilities') + for [l:dir, l:project] in l:uninitialized_projects + call s:MarkProjectAsInitialized(a:conn, l:project) + endfor + endif + elseif get(a:response, 'method', '') ==# 'textDocument/publishDiagnostics' let l:filename = ale#path#FromURI(a:response.params.uri) for [l:dir, l:project] in l:uninitialized_projects @@ -237,7 +243,7 @@ function! s:HandleCommandMessage(job_id, message) abort endfunction function! s:RegisterProject(conn, project_root) abort - if !has_key(a:conn, a:project_root) + if !has_key(a:conn.projects, a:project_root) " Tools without project roots are ready right away, like tsserver. let a:conn.projects[a:project_root] = { \ 'initialized': empty(a:project_root),