aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assist_config.rs5
-rw-r--r--crates/ra_assists/src/assist_context.rs8
-rw-r--r--crates/ra_assists/src/lib.rs12
-rw-r--r--crates/ra_assists/src/tests.rs25
-rw-r--r--crates/ra_ide/src/lib.rs6
-rw-r--r--crates/rust-analyzer/src/handlers.rs28
6 files changed, 40 insertions, 44 deletions
diff --git a/crates/ra_assists/src/assist_config.rs b/crates/ra_assists/src/assist_config.rs
index c0a0226fb..cda2abfb9 100644
--- a/crates/ra_assists/src/assist_config.rs
+++ b/crates/ra_assists/src/assist_config.rs
@@ -4,9 +4,12 @@
4//! module, and we use to statically check that we only produce snippet 4//! module, and we use to statically check that we only produce snippet
5//! assists if we are allowed to. 5//! assists if we are allowed to.
6 6
7use crate::AssistKind;
8
7#[derive(Clone, Debug, PartialEq, Eq)] 9#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct AssistConfig { 10pub struct AssistConfig {
9 pub snippet_cap: Option<SnippetCap>, 11 pub snippet_cap: Option<SnippetCap>,
12 pub allowed: Option<Vec<AssistKind>>,
10} 13}
11 14
12impl AssistConfig { 15impl AssistConfig {
@@ -22,6 +25,6 @@ pub struct SnippetCap {
22 25
23impl Default for AssistConfig { 26impl Default for AssistConfig {
24 fn default() -> Self { 27 fn default() -> Self {
25 AssistConfig { snippet_cap: Some(SnippetCap { _private: () }) } 28 AssistConfig { snippet_cap: Some(SnippetCap { _private: () }), allowed: None }
26 } 29 }
27} 30}
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
index 9ca2cfe68..3407df856 100644
--- a/crates/ra_assists/src/assist_context.rs
+++ b/crates/ra_assists/src/assist_context.rs
@@ -57,7 +57,6 @@ pub(crate) struct AssistContext<'a> {
57 pub(crate) sema: Semantics<'a, RootDatabase>, 57 pub(crate) sema: Semantics<'a, RootDatabase>,
58 pub(crate) frange: FileRange, 58 pub(crate) frange: FileRange,
59 source_file: SourceFile, 59 source_file: SourceFile,
60 allowed: Option<Vec<AssistKind>>,
61} 60}
62 61
63impl<'a> AssistContext<'a> { 62impl<'a> AssistContext<'a> {
@@ -65,10 +64,9 @@ impl<'a> AssistContext<'a> {
65 sema: Semantics<'a, RootDatabase>, 64 sema: Semantics<'a, RootDatabase>,
66 config: &'a AssistConfig, 65 config: &'a AssistConfig,
67 frange: FileRange, 66 frange: FileRange,
68 allowed: Option<Vec<AssistKind>>,
69 ) -> AssistContext<'a> { 67 ) -> AssistContext<'a> {
70 let source_file = sema.parse(frange.file_id); 68 let source_file = sema.parse(frange.file_id);
71 AssistContext { config, sema, frange, source_file, allowed } 69 AssistContext { config, sema, frange, source_file }
72 } 70 }
73 71
74 pub(crate) fn db(&self) -> &RootDatabase { 72 pub(crate) fn db(&self) -> &RootDatabase {
@@ -114,7 +112,7 @@ impl Assists {
114 resolve: true, 112 resolve: true,
115 file: ctx.frange.file_id, 113 file: ctx.frange.file_id,
116 buf: Vec::new(), 114 buf: Vec::new(),
117 allowed: ctx.allowed.clone(), 115 allowed: ctx.config.allowed.clone(),
118 } 116 }
119 } 117 }
120 118
@@ -123,7 +121,7 @@ impl Assists {
123 resolve: false, 121 resolve: false,
124 file: ctx.frange.file_id, 122 file: ctx.frange.file_id,
125 buf: Vec::new(), 123 buf: Vec::new(),
126 allowed: ctx.allowed.clone(), 124 allowed: ctx.config.allowed.clone(),
127 } 125 }
128 } 126 }
129 127
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 13a283760..465b90415 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -86,14 +86,9 @@ impl Assist {
86 /// 86 ///
87 /// Assists are returned in the "unresolved" state, that is only labels are 87 /// Assists are returned in the "unresolved" state, that is only labels are
88 /// returned, without actual edits. 88 /// returned, without actual edits.
89 pub fn unresolved( 89 pub fn unresolved(db: &RootDatabase, config: &AssistConfig, range: FileRange) -> Vec<Assist> {
90 db: &RootDatabase,
91 config: &AssistConfig,
92 range: FileRange,
93 allowed: Option<Vec<AssistKind>>,
94 ) -> Vec<Assist> {
95 let sema = Semantics::new(db); 90 let sema = Semantics::new(db);
96 let ctx = AssistContext::new(sema, config, range, allowed); 91 let ctx = AssistContext::new(sema, config, range);
97 let mut acc = Assists::new_unresolved(&ctx); 92 let mut acc = Assists::new_unresolved(&ctx);
98 handlers::all().iter().for_each(|handler| { 93 handlers::all().iter().for_each(|handler| {
99 handler(&mut acc, &ctx); 94 handler(&mut acc, &ctx);
@@ -109,10 +104,9 @@ impl Assist {
109 db: &RootDatabase, 104 db: &RootDatabase,
110 config: &AssistConfig, 105 config: &AssistConfig,
111 range: FileRange, 106 range: FileRange,
112 allowed: Option<Vec<AssistKind>>,
113 ) -> Vec<ResolvedAssist> { 107 ) -> Vec<ResolvedAssist> {
114 let sema = Semantics::new(db); 108 let sema = Semantics::new(db);
115 let ctx = AssistContext::new(sema, config, range, allowed); 109 let ctx = AssistContext::new(sema, config, range);
116 let mut acc = Assists::new_resolved(&ctx); 110 let mut acc = Assists::new_resolved(&ctx);
117 handlers::all().iter().for_each(|handler| { 111 handlers::all().iter().for_each(|handler| {
118 handler(&mut acc, &ctx); 112 handler(&mut acc, &ctx);
diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs
index 861622d86..18fcb9049 100644
--- a/crates/ra_assists/src/tests.rs
+++ b/crates/ra_assists/src/tests.rs
@@ -35,14 +35,14 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
35 let before = db.file_text(file_id).to_string(); 35 let before = db.file_text(file_id).to_string();
36 let frange = FileRange { file_id, range: selection.into() }; 36 let frange = FileRange { file_id, range: selection.into() };
37 37
38 let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange, None) 38 let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange)
39 .into_iter() 39 .into_iter()
40 .find(|assist| assist.assist.id.0 == assist_id) 40 .find(|assist| assist.assist.id.0 == assist_id)
41 .unwrap_or_else(|| { 41 .unwrap_or_else(|| {
42 panic!( 42 panic!(
43 "\n\nAssist is not applicable: {}\nAvailable assists: {}", 43 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
44 assist_id, 44 assist_id,
45 Assist::resolved(&db, &AssistConfig::default(), frange, None) 45 Assist::resolved(&db, &AssistConfig::default(), frange)
46 .into_iter() 46 .into_iter()
47 .map(|assist| assist.assist.id.0) 47 .map(|assist| assist.assist.id.0)
48 .collect::<Vec<_>>() 48 .collect::<Vec<_>>()
@@ -73,7 +73,7 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult) {
73 73
74 let sema = Semantics::new(&db); 74 let sema = Semantics::new(&db);
75 let config = AssistConfig::default(); 75 let config = AssistConfig::default();
76 let ctx = AssistContext::new(sema, &config, frange, None); 76 let ctx = AssistContext::new(sema, &config, frange);
77 let mut acc = Assists::new_resolved(&ctx); 77 let mut acc = Assists::new_resolved(&ctx);
78 handler(&mut acc, &ctx); 78 handler(&mut acc, &ctx);
79 let mut res = acc.finish_resolved(); 79 let mut res = acc.finish_resolved();
@@ -105,7 +105,7 @@ fn assist_order_field_struct() {
105 let (before_cursor_pos, before) = extract_offset(before); 105 let (before_cursor_pos, before) = extract_offset(before);
106 let (db, file_id) = with_single_file(&before); 106 let (db, file_id) = with_single_file(&before);
107 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) }; 107 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
108 let assists = Assist::resolved(&db, &AssistConfig::default(), frange, None); 108 let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
109 let mut assists = assists.iter(); 109 let mut assists = assists.iter();
110 110
111 assert_eq!( 111 assert_eq!(
@@ -128,7 +128,7 @@ fn assist_order_if_expr() {
128 let (range, before) = extract_range(before); 128 let (range, before) = extract_range(before);
129 let (db, file_id) = with_single_file(&before); 129 let (db, file_id) = with_single_file(&before);
130 let frange = FileRange { file_id, range }; 130 let frange = FileRange { file_id, range };
131 let assists = Assist::resolved(&db, &AssistConfig::default(), frange, None); 131 let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
132 let mut assists = assists.iter(); 132 let mut assists = assists.iter();
133 133
134 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable"); 134 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
@@ -150,9 +150,10 @@ fn assist_filter_works() {
150 let frange = FileRange { file_id, range }; 150 let frange = FileRange { file_id, range };
151 151
152 { 152 {
153 let allowed = Some(vec![AssistKind::Refactor]); 153 let mut cfg = AssistConfig::default();
154 cfg.allowed = Some(vec![AssistKind::Refactor]);
154 155
155 let assists = Assist::resolved(&db, &AssistConfig::default(), frange, allowed); 156 let assists = Assist::resolved(&db, &cfg, frange);
156 let mut assists = assists.iter(); 157 let mut assists = assists.iter();
157 158
158 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable"); 159 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
@@ -160,8 +161,9 @@ fn assist_filter_works() {
160 } 161 }
161 162
162 { 163 {
163 let allowed = Some(vec![AssistKind::RefactorExtract]); 164 let mut cfg = AssistConfig::default();
164 let assists = Assist::resolved(&db, &AssistConfig::default(), frange, allowed); 165 cfg.allowed = Some(vec![AssistKind::RefactorExtract]);
166 let assists = Assist::resolved(&db, &cfg, frange);
165 assert_eq!(assists.len(), 1); 167 assert_eq!(assists.len(), 1);
166 168
167 let mut assists = assists.iter(); 169 let mut assists = assists.iter();
@@ -169,8 +171,9 @@ fn assist_filter_works() {
169 } 171 }
170 172
171 { 173 {
172 let allowed = Some(vec![AssistKind::QuickFix]); 174 let mut cfg = AssistConfig::default();
173 let assists = Assist::resolved(&db, &AssistConfig::default(), frange, allowed); 175 cfg.allowed = Some(vec![AssistKind::QuickFix]);
176 let assists = Assist::resolved(&db, &cfg, frange);
174 assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out"); 177 assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out");
175 } 178 }
176} 179}
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index c21f2a0b1..6a4f5cb3d 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -476,9 +476,8 @@ impl Analysis {
476 &self, 476 &self,
477 config: &AssistConfig, 477 config: &AssistConfig,
478 frange: FileRange, 478 frange: FileRange,
479 allowed: Option<Vec<AssistKind>>,
480 ) -> Cancelable<Vec<ResolvedAssist>> { 479 ) -> Cancelable<Vec<ResolvedAssist>> {
481 self.with_db(|db| ra_assists::Assist::resolved(db, config, frange, allowed)) 480 self.with_db(|db| ra_assists::Assist::resolved(db, config, frange))
482 } 481 }
483 482
484 /// Computes unresolved assists (aka code actions aka intentions) for the given 483 /// Computes unresolved assists (aka code actions aka intentions) for the given
@@ -487,9 +486,8 @@ impl Analysis {
487 &self, 486 &self,
488 config: &AssistConfig, 487 config: &AssistConfig,
489 frange: FileRange, 488 frange: FileRange,
490 allowed: Option<Vec<AssistKind>>,
491 ) -> Cancelable<Vec<Assist>> { 489 ) -> Cancelable<Vec<Assist>> {
492 self.with_db(|db| Assist::unresolved(db, config, frange, allowed)) 490 self.with_db(|db| Assist::unresolved(db, config, frange))
493 } 491 }
494 492
495 /// Computes the set of diagnostics for the given file. 493 /// Computes the set of diagnostics for the given file.
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 2b37d7825..d28c700f1 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -790,7 +790,7 @@ fn handle_fixes(
790} 790}
791 791
792pub(crate) fn handle_code_action( 792pub(crate) fn handle_code_action(
793 snap: GlobalStateSnapshot, 793 mut snap: GlobalStateSnapshot,
794 params: lsp_types::CodeActionParams, 794 params: lsp_types::CodeActionParams,
795) -> Result<Option<Vec<lsp_ext::CodeAction>>> { 795) -> Result<Option<Vec<lsp_ext::CodeAction>>> {
796 let _p = profile("handle_code_action"); 796 let _p = profile("handle_code_action");
@@ -806,25 +806,24 @@ pub(crate) fn handle_code_action(
806 let range = from_proto::text_range(&line_index, params.range); 806 let range = from_proto::text_range(&line_index, params.range);
807 let frange = FileRange { file_id, range }; 807 let frange = FileRange { file_id, range };
808 808
809 snap.config.assist.allowed = params
810 .clone()
811 .context
812 .only
813 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
814
809 let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); 815 let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
810 816
811 handle_fixes(&snap, &params, &mut res)?; 817 handle_fixes(&snap, &params, &mut res)?;
812 818
813 let only =
814 params.context.only.map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
815
816 if snap.config.client_caps.resolve_code_action { 819 if snap.config.client_caps.resolve_code_action {
817 for (index, assist) in snap 820 for (index, assist) in
818 .analysis 821 snap.analysis.unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate()
819 .unresolved_assists(&snap.config.assist, frange, only)?
820 .into_iter()
821 .enumerate()
822 { 822 {
823 res.push(to_proto::unresolved_code_action(&snap, assist, index)?); 823 res.push(to_proto::unresolved_code_action(&snap, assist, index)?);
824 } 824 }
825 } else { 825 } else {
826 for assist in snap.analysis.resolved_assists(&snap.config.assist, frange, only)?.into_iter() 826 for assist in snap.analysis.resolved_assists(&snap.config.assist, frange)?.into_iter() {
827 {
828 res.push(to_proto::resolved_code_action(&snap, assist)?); 827 res.push(to_proto::resolved_code_action(&snap, assist)?);
829 } 828 }
830 } 829 }
@@ -833,7 +832,7 @@ pub(crate) fn handle_code_action(
833} 832}
834 833
835pub(crate) fn handle_resolve_code_action( 834pub(crate) fn handle_resolve_code_action(
836 snap: GlobalStateSnapshot, 835 mut snap: GlobalStateSnapshot,
837 params: lsp_ext::ResolveCodeActionParams, 836 params: lsp_ext::ResolveCodeActionParams,
838) -> Result<Option<lsp_ext::SnippetWorkspaceEdit>> { 837) -> Result<Option<lsp_ext::SnippetWorkspaceEdit>> {
839 let _p = profile("handle_resolve_code_action"); 838 let _p = profile("handle_resolve_code_action");
@@ -841,13 +840,14 @@ pub(crate) fn handle_resolve_code_action(
841 let line_index = snap.analysis.file_line_index(file_id)?; 840 let line_index = snap.analysis.file_line_index(file_id)?;
842 let range = from_proto::text_range(&line_index, params.code_action_params.range); 841 let range = from_proto::text_range(&line_index, params.code_action_params.range);
843 let frange = FileRange { file_id, range }; 842 let frange = FileRange { file_id, range };
844 let only = params 843
844 snap.config.assist.allowed = params
845 .code_action_params 845 .code_action_params
846 .context 846 .context
847 .only 847 .only
848 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); 848 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
849 849
850 let assists = snap.analysis.resolved_assists(&snap.config.assist, frange, only)?; 850 let assists = snap.analysis.resolved_assists(&snap.config.assist, frange)?;
851 let (id_string, index) = split_delim(&params.id, ':').unwrap(); 851 let (id_string, index) = split_delim(&params.id, ':').unwrap();
852 let index = index.parse::<usize>().unwrap(); 852 let index = index.parse::<usize>().unwrap();
853 let assist = &assists[index]; 853 let assist = &assists[index];