Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions autoload/LanguageClient.vim
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,22 @@ function! LanguageClient#setLoggingLevel(level) abort
return LanguageClient#Call('languageClient/setLoggingLevel', l:params, v:null)
endfunction

function! LanguageClient#diagnosticsPrevious() abort
let l:params = {
\ 'filename': LSP#filename(),
\ 'position': LSP#position(),
\ }
return LanguageClient#Notify('languageClient/diagnosticsPrevious', l:params)
endfunction

function! LanguageClient#diagnosticsNext() abort
let l:params = {
\ 'filename': LSP#filename(),
\ 'position': LSP#position(),
\ }
return LanguageClient#Notify('languageClient/diagnosticsNext', l:params)
endfunction

function! LanguageClient#setDiagnosticsList(diagnosticsList) abort
let l:params = {
\ 'diagnosticsList': a:diagnosticsList,
Expand Down
17 changes: 17 additions & 0 deletions doc/LanguageClient.txt
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,17 @@ Signature: LanguageClient#debugInfo(...)

Print out debug info.

*LanguageClient#diagnosticsNext*
Signature: LanguageClient#diagnosticsNext()

Moves the cursor to the next diagnostic in the buffer, relative to the current cursor position.

*LanguageClient#diagnosticsPrevious*
Signature: LanguageClient#diagnosticsPrevious()

Moves the cursor to the previous diagnostic in the buffer, relative to the current cursor position.


==============================================================================
5. Mappings *LanguageClientMappings*

Expand Down Expand Up @@ -959,6 +970,12 @@ Calls LanguageClient_textDocument_formatting.
*(lcn-format-sync)*
Calls LanguageClient_textDocument_formatting_sync.

*(lcn-diagnostics-next)*
Calls LanguageClient_diagnosticsNext.

*(lcn-diagnostics-prev)*
Calls LanguageClient_diagnosticsPrevious.


==============================================================================
6. Events *LanguageClientEvents*
Expand Down
10 changes: 10 additions & 0 deletions plugin/LanguageClient.vim
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ function! LanguageClient_statusLine(...)
return call('LanguageClient#statusLine', a:000)
endfunction

function! LanguageClient_diagnosticsPrevious(...)
return call('LanguageClient#diagnosticsPrevious', a:000)
endfunction

function! LanguageClient_diagnosticsNext(...)
return call('LanguageClient#diagnosticsNext', a:000)
endfunction

function! LanguageClient_statusLineDiagnosticsCounts(...)
return call('LanguageClient#statusLineDiagnosticsCounts', a:000)
endfunction
Expand Down Expand Up @@ -178,4 +186,6 @@ augroup languageClient
nnoremap <Plug>(lcn-explain-error) :call LanguageClient_explainErrorAtPoint()<CR>
nnoremap <Plug>(lcn-format) :call LanguageClient_textDocument_formatting()<CR>
nnoremap <Plug>(lcn-format-sync) :call LanguageClient_textDocument_formatting_sync()<CR>
nnoremap <Plug>(lcn-diagnostics-next) :call LanguageClient_diagnosticsNext()<CR>
nnoremap <Plug>(lcn-diagnostics-prev) :call LanguageClient_diagnosticsPrevious()<CR>
augroup END
6 changes: 3 additions & 3 deletions src/language_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ impl LanguageClient {
// garbage collected as a result of another modification updating the hash map, while something was holding the lock
pub fn get_client_update_mutex(&self, language_id: LanguageId) -> Result<Arc<Mutex<()>>> {
let map_guard = self.clients_mutex.lock();
let mut map = map_guard.or_else(|err| {
Err(anyhow!(
let mut map = map_guard.map_err(|err| {
anyhow!(
"Failed to lock client creation for languageId {:?}: {:?}",
language_id,
err,
))
)
})?;
if !map.contains_key(&language_id) {
map.insert(language_id.clone(), Arc::new(Mutex::new(())));
Expand Down
45 changes: 45 additions & 0 deletions src/language_server_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ use std::{
time::{Duration, Instant},
};

#[derive(PartialEq)]
pub enum Direction {
Next,
Previous,
}

impl LanguageClient {
pub fn get_client(&self, language_id: &LanguageId) -> Result<Arc<RpcClient>> {
self.get(|state| state.clients.get(language_id).cloned())?
Expand Down Expand Up @@ -603,6 +609,45 @@ impl LanguageClient {
Ok(position)
}

// moves the cursor to the next or previous diagnostic, depending on the value of direction.
pub fn cycle_diagnostics(&self, params: &Value, direction: Direction) -> Result<()> {
let filename = self.vim()?.get_filename(params)?;
let pos = self.vim()?.get_position(params)?;
let mut diagnostics = self.get(|state| state.diagnostics.clone())?;
if let Some(diagnostics) = diagnostics.get_mut(&filename) {
if direction == Direction::Next {
diagnostics.sort_by_key(|edit| (edit.range.start.line, edit.range.start.character));
} else {
diagnostics.sort_by_key(|edit| {
(
-(edit.range.start.line as i64),
-(edit.range.start.character as i64),
)
});
}

let (line, col) = (pos.line, pos.character);
if let Some((_, diagnostic)) = diagnostics.iter_mut().find_position(|it| {
let start = it.range.start;
if direction == Direction::Next {
start.line > line || (start.line == line && start.character > col)
} else {
start.line < line || (start.line == line && start.character < col)
}
}) {
let line = diagnostic.range.start.line + 1;
let col = diagnostic.range.start.character + 1;
let _: String = self.vim()?.rpcclient.call("cursor", json!([line, col]))?;
} else {
self.vim()?.echomsg("No diagnostics found")?;
}
} else {
self.vim()?.echomsg("No diagnostics found")?;
}

Ok(())
}

fn update_quickfixlist(&self) -> Result<()> {
let diagnostics = self.get(|state| state.diagnostics.clone())?;
let qflist: Vec<_> = diagnostics
Expand Down
6 changes: 5 additions & 1 deletion src/rpchandler.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{language_client::LanguageClient, types::*};
use crate::{language_client::LanguageClient, language_server_protocol::Direction, types::*};
use anyhow::{anyhow, Result};
use log::*;
use lsp_types::notification::{self, Notification};
Expand Down Expand Up @@ -196,6 +196,10 @@ impl LanguageClient {
NOTIFICATION_RUST_BEGIN_BUILD => self.rust_handle_begin_build(&params)?,
NOTIFICATION_RUST_DIAGNOSTICS_BEGIN => self.rust_handle_diagnostics_begin(&params)?,
NOTIFICATION_RUST_DIAGNOSTICS_END => self.rust_handle_diagnostics_end(&params)?,
NOTIFICATION_DIAGNOSTICS_NEXT => self.cycle_diagnostics(&params, Direction::Next)?,
NOTIFICATION_DIAGNOSTICS_PREVIOUS => {
self.cycle_diagnostics(&params, Direction::Previous)?
}

_ => {
let language_id_target = if language_id.is_some() {
Expand Down
2 changes: 2 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ pub const NOTIFICATION_RUST_DIAGNOSTICS_BEGIN: &str = "rustDocument/diagnosticsB
pub const NOTIFICATION_RUST_DIAGNOSTICS_END: &str = "rustDocument/diagnosticsEnd";
pub const NOTIFICATION_WINDOW_PROGRESS: &str = "window/progress";
pub const NOTIFICATION_LANGUAGE_STATUS: &str = "language/status";
pub const NOTIFICATION_DIAGNOSTICS_NEXT: &str = "languageClient/diagnosticsNext";
pub const NOTIFICATION_DIAGNOSTICS_PREVIOUS: &str = "languageClient/diagnosticsPrevious";

pub const VIM_SERVER_STATUS: &str = "g:LanguageClient_serverStatus";
pub const VIM_SERVER_STATUS_MESSAGE: &str = "g:LanguageClient_serverStatusMessage";
Expand Down
2 changes: 1 addition & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ impl<P: AsRef<Path> + std::fmt::Debug> ToUrl for P {
fn to_url(&self) -> Result<Url> {
Url::from_file_path(self)
.or_else(|_| Url::from_str(&self.as_ref().to_string_lossy()))
.or_else(|_| Err(anyhow!("Failed to convert ({:?}) to Url", self)))
.map_err(|_| anyhow!("Failed to convert ({:?}) to Url", self))
}
}

Expand Down