aboutsummaryrefslogtreecommitdiff
path: root/crates/rust-analyzer/src/main_loop/handlers.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-06-03 21:31:25 +0100
committerGitHub <[email protected]>2020-06-03 21:31:25 +0100
commit65a3cc21edd8acd93b728d094514bafddcb1757a (patch)
tree8327b508541f80ff539c2b13559e7f2df2fe4d6b /crates/rust-analyzer/src/main_loop/handlers.rs
parent794f6da821c5d6e2490b996baffe162e4753262d (diff)
parent6cd2e04bd2a703c335566224e8b6bf773b83c0c6 (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.rs77
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;
25use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize}; 25use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize};
26use serde::{Deserialize, Serialize}; 26use serde::{Deserialize, Serialize};
27use serde_json::to_value; 27use serde_json::to_value;
28use stdx::format_to; 28use stdx::{format_to, split1};
29 29
30use crate::{ 30use 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
704pub fn handle_code_action( 704fn 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, &params.text_document.uri)?; 709 let file_id = from_proto::file_id(&snap, &params.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
743pub 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, &params.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, &params, &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
778pub 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, &params.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(&params.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
757pub fn handle_code_lens( 796pub fn handle_code_lens(
758 snap: GlobalStateSnapshot, 797 snap: GlobalStateSnapshot,
759 params: lsp_types::CodeLensParams, 798 params: lsp_types::CodeLensParams,