aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/main_loop/handlers.rs
diff options
context:
space:
mode:
authorEmil Lauridsen <[email protected]>2020-01-31 18:23:25 +0000
committerEmil Lauridsen <[email protected]>2020-02-03 10:34:24 +0000
commit790788d5f4013d8d92f110bc12a581d18cf4b6ae (patch)
tree311e11529c7546b7a09486d5c161039d8bd8f975 /crates/ra_lsp_server/src/main_loop/handlers.rs
parent52456c44901c8c38c8bcb742ebe305484af8f36f (diff)
Rework how we send diagnostics to client.
The previous way of sending from the thread pool suffered from stale diagnostics due to being canceled before we could clear the old ones. The key change is moving to sending diagnostics from the main loop thread, but doing all the hard work in the thread pool. This should provide the best of both worlds, with little to no of the downsides. This should hopefully fix a lot of issues, but we'll need testing in each individual issue to be sure.
Diffstat (limited to 'crates/ra_lsp_server/src/main_loop/handlers.rs')
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs37
1 files changed, 8 insertions, 29 deletions
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 9aa1e7eea..839bca342 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -33,6 +33,7 @@ use crate::{
33 to_call_hierarchy_item, to_location, Conv, ConvWith, FoldConvCtx, MapConvWith, TryConvWith, 33 to_call_hierarchy_item, to_location, Conv, ConvWith, FoldConvCtx, MapConvWith, TryConvWith,
34 TryConvWithToVec, 34 TryConvWithToVec,
35 }, 35 },
36 diagnostics::DiagnosticTask,
36 req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind}, 37 req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
37 world::WorldSnapshot, 38 world::WorldSnapshot,
38 LspError, Result, 39 LspError, Result,
@@ -656,6 +657,7 @@ pub fn handle_code_action(
656 .filter(|(diag_range, _fix)| diag_range.intersection(&range).is_some()) 657 .filter(|(diag_range, _fix)| diag_range.intersection(&range).is_some())
657 .map(|(_range, fix)| fix); 658 .map(|(_range, fix)| fix);
658 659
660 // TODO: When done, we won't need this, only the one pulling from world.diagnostics
659 for source_edit in fixes_from_diagnostics { 661 for source_edit in fixes_from_diagnostics {
660 let title = source_edit.label.clone(); 662 let title = source_edit.label.clone();
661 let edit = source_edit.try_conv_with(&world)?; 663 let edit = source_edit.try_conv_with(&world)?;
@@ -676,28 +678,12 @@ pub fn handle_code_action(
676 res.push(action.into()); 678 res.push(action.into());
677 } 679 }
678 680
679 for fix in world.check_watcher.fixes_for(&params.text_document.uri).into_iter().flatten() { 681 for fix in world.check_fixes.get(&file_id).into_iter().flatten() {
680 let fix_range = fix.location.range.conv_with(&line_index); 682 let fix_range = fix.range.conv_with(&line_index);
681 if fix_range.intersection(&range).is_none() { 683 if fix_range.intersection(&range).is_none() {
682 continue; 684 continue;
683 } 685 }
684 686 res.push(fix.action.clone());
685 let edit = {
686 let edits = vec![TextEdit::new(fix.location.range, fix.replacement.clone())];
687 let mut edit_map = std::collections::HashMap::new();
688 edit_map.insert(fix.location.uri.clone(), edits);
689 WorkspaceEdit::new(edit_map)
690 };
691
692 let action = CodeAction {
693 title: fix.title.clone(),
694 kind: Some("quickfix".to_string()),
695 diagnostics: Some(fix.diagnostics.clone()),
696 edit: Some(edit),
697 command: None,
698 is_preferred: None,
699 };
700 res.push(action.into());
701 } 687 }
702 688
703 for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() { 689 for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() {
@@ -875,14 +861,10 @@ pub fn handle_document_highlight(
875 )) 861 ))
876} 862}
877 863
878pub fn publish_diagnostics( 864pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<DiagnosticTask> {
879 world: &WorldSnapshot,
880 file_id: FileId,
881) -> Result<req::PublishDiagnosticsParams> {
882 let _p = profile("publish_diagnostics"); 865 let _p = profile("publish_diagnostics");
883 let uri = world.file_id_to_uri(file_id)?;
884 let line_index = world.analysis().file_line_index(file_id)?; 866 let line_index = world.analysis().file_line_index(file_id)?;
885 let mut diagnostics: Vec<Diagnostic> = world 867 let diagnostics: Vec<Diagnostic> = world
886 .analysis() 868 .analysis()
887 .diagnostics(file_id)? 869 .diagnostics(file_id)?
888 .into_iter() 870 .into_iter()
@@ -896,10 +878,7 @@ pub fn publish_diagnostics(
896 tags: None, 878 tags: None,
897 }) 879 })
898 .collect(); 880 .collect();
899 if let Some(check_diags) = world.check_watcher.diagnostics_for(&uri) { 881 Ok(DiagnosticTask::SetNative(file_id, diagnostics))
900 diagnostics.extend(check_diags.iter().cloned());
901 }
902 Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None })
903} 882}
904 883
905pub fn publish_decorations( 884pub fn publish_decorations(