diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-06-03 21:31:25 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-06-03 21:31:25 +0100 |
commit | 65a3cc21edd8acd93b728d094514bafddcb1757a (patch) | |
tree | 8327b508541f80ff539c2b13559e7f2df2fe4d6b /crates/rust-analyzer/src/main_loop/handlers.rs | |
parent | 794f6da821c5d6e2490b996baffe162e4753262d (diff) | |
parent | 6cd2e04bd2a703c335566224e8b6bf773b83c0c6 (diff) |
Merge #4717
4717: Implementation of lazy assits r=matklad a=mcrakhman
Co-authored-by: Mikhail Rakhmanov <[email protected]>
Diffstat (limited to 'crates/rust-analyzer/src/main_loop/handlers.rs')
-rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index c2a5bf4d6..6acf80c58 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -25,7 +25,7 @@ use ra_project_model::TargetKind; | |||
25 | use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize}; | 25 | use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize}; |
26 | use serde::{Deserialize, Serialize}; | 26 | use serde::{Deserialize, Serialize}; |
27 | use serde_json::to_value; | 27 | use serde_json::to_value; |
28 | use stdx::format_to; | 28 | use stdx::{format_to, split1}; |
29 | 29 | ||
30 | use crate::{ | 30 | use crate::{ |
31 | cargo_target_spec::CargoTargetSpec, | 31 | cargo_target_spec::CargoTargetSpec, |
@@ -701,37 +701,27 @@ pub fn handle_formatting( | |||
701 | }])) | 701 | }])) |
702 | } | 702 | } |
703 | 703 | ||
704 | pub fn handle_code_action( | 704 | fn handle_fixes( |
705 | snap: GlobalStateSnapshot, | 705 | snap: &GlobalStateSnapshot, |
706 | params: lsp_types::CodeActionParams, | 706 | params: &lsp_types::CodeActionParams, |
707 | ) -> Result<Option<Vec<lsp_ext::CodeAction>>> { | 707 | res: &mut Vec<lsp_ext::CodeAction>, |
708 | let _p = profile("handle_code_action"); | 708 | ) -> Result<()> { |
709 | // We intentionally don't support command-based actions, as those either | ||
710 | // requires custom client-code anyway, or requires server-initiated edits. | ||
711 | // Server initiated edits break causality, so we avoid those as well. | ||
712 | if !snap.config.client_caps.code_action_literals { | ||
713 | return Ok(None); | ||
714 | } | ||
715 | |||
716 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 709 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
717 | let line_index = snap.analysis().file_line_index(file_id)?; | 710 | let line_index = snap.analysis().file_line_index(file_id)?; |
718 | let range = from_proto::text_range(&line_index, params.range); | 711 | let range = from_proto::text_range(&line_index, params.range); |
719 | let frange = FileRange { file_id, range }; | ||
720 | |||
721 | let diagnostics = snap.analysis().diagnostics(file_id)?; | 712 | let diagnostics = snap.analysis().diagnostics(file_id)?; |
722 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); | ||
723 | 713 | ||
724 | let fixes_from_diagnostics = diagnostics | 714 | let fixes_from_diagnostics = diagnostics |
725 | .into_iter() | 715 | .into_iter() |
726 | .filter_map(|d| Some((d.range, d.fix?))) | 716 | .filter_map(|d| Some((d.range, d.fix?))) |
727 | .filter(|(diag_range, _fix)| diag_range.intersect(range).is_some()) | 717 | .filter(|(diag_range, _fix)| diag_range.intersect(range).is_some()) |
728 | .map(|(_range, fix)| fix); | 718 | .map(|(_range, fix)| fix); |
729 | |||
730 | for fix in fixes_from_diagnostics { | 719 | for fix in fixes_from_diagnostics { |
731 | let title = fix.label; | 720 | let title = fix.label; |
732 | let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?; | 721 | let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?; |
733 | let action = lsp_ext::CodeAction { | 722 | let action = lsp_ext::CodeAction { |
734 | title, | 723 | title, |
724 | id: None, | ||
735 | group: None, | 725 | group: None, |
736 | kind: Some(lsp_types::code_action_kind::QUICKFIX.into()), | 726 | kind: Some(lsp_types::code_action_kind::QUICKFIX.into()), |
737 | edit: Some(edit), | 727 | edit: Some(edit), |
@@ -747,13 +737,62 @@ pub fn handle_code_action( | |||
747 | } | 737 | } |
748 | res.push(fix.action.clone()); | 738 | res.push(fix.action.clone()); |
749 | } | 739 | } |
740 | Ok(()) | ||
741 | } | ||
742 | |||
743 | pub fn handle_code_action( | ||
744 | snap: GlobalStateSnapshot, | ||
745 | params: lsp_types::CodeActionParams, | ||
746 | ) -> Result<Option<Vec<lsp_ext::CodeAction>>> { | ||
747 | let _p = profile("handle_code_action"); | ||
748 | // We intentionally don't support command-based actions, as those either | ||
749 | // requires custom client-code anyway, or requires server-initiated edits. | ||
750 | // Server initiated edits break causality, so we avoid those as well. | ||
751 | if !snap.config.client_caps.code_action_literals { | ||
752 | return Ok(None); | ||
753 | } | ||
754 | |||
755 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | ||
756 | let line_index = snap.analysis().file_line_index(file_id)?; | ||
757 | let range = from_proto::text_range(&line_index, params.range); | ||
758 | let frange = FileRange { file_id, range }; | ||
759 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); | ||
750 | 760 | ||
751 | for assist in snap.analysis().assists(&snap.config.assist, frange)?.into_iter() { | 761 | handle_fixes(&snap, ¶ms, &mut res)?; |
752 | res.push(to_proto::code_action(&snap, assist)?.into()); | 762 | |
763 | if snap.config.client_caps.resolve_code_action { | ||
764 | for (index, assist) in | ||
765 | snap.analysis().unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate() | ||
766 | { | ||
767 | res.push(to_proto::unresolved_code_action(&snap, assist, index)?); | ||
768 | } | ||
769 | } else { | ||
770 | for assist in snap.analysis().resolved_assists(&snap.config.assist, frange)?.into_iter() { | ||
771 | res.push(to_proto::resolved_code_action(&snap, assist)?); | ||
772 | } | ||
753 | } | 773 | } |
774 | |||
754 | Ok(Some(res)) | 775 | Ok(Some(res)) |
755 | } | 776 | } |
756 | 777 | ||
778 | pub fn handle_resolve_code_action( | ||
779 | snap: GlobalStateSnapshot, | ||
780 | params: lsp_ext::ResolveCodeActionParams, | ||
781 | ) -> Result<Option<lsp_ext::SnippetWorkspaceEdit>> { | ||
782 | let _p = profile("handle_resolve_code_action"); | ||
783 | let file_id = from_proto::file_id(&snap, ¶ms.code_action_params.text_document.uri)?; | ||
784 | let line_index = snap.analysis().file_line_index(file_id)?; | ||
785 | let range = from_proto::text_range(&line_index, params.code_action_params.range); | ||
786 | let frange = FileRange { file_id, range }; | ||
787 | |||
788 | let assists = snap.analysis().resolved_assists(&snap.config.assist, frange)?; | ||
789 | let (id_string, index) = split1(¶ms.id, ':').unwrap(); | ||
790 | let index = index.parse::<usize>().unwrap(); | ||
791 | let assist = &assists[index]; | ||
792 | assert!(assist.assist.id.0 == id_string); | ||
793 | Ok(to_proto::resolved_code_action(&snap, assist.clone())?.edit) | ||
794 | } | ||
795 | |||
757 | pub fn handle_code_lens( | 796 | pub fn handle_code_lens( |
758 | snap: GlobalStateSnapshot, | 797 | snap: GlobalStateSnapshot, |
759 | params: lsp_types::CodeLensParams, | 798 | params: lsp_types::CodeLensParams, |