diff options
author | Emil Lauridsen <[email protected]> | 2020-01-31 18:23:25 +0000 |
---|---|---|
committer | Emil Lauridsen <[email protected]> | 2020-02-03 10:34:24 +0000 |
commit | 790788d5f4013d8d92f110bc12a581d18cf4b6ae (patch) | |
tree | 311e11529c7546b7a09486d5c161039d8bd8f975 /crates/ra_lsp_server/src/main_loop/handlers.rs | |
parent | 52456c44901c8c38c8bcb742ebe305484af8f36f (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.rs | 37 |
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(¶ms.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 | ||
878 | pub fn publish_diagnostics( | 864 | pub 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 | ||
905 | pub fn publish_decorations( | 884 | pub fn publish_decorations( |