diff options
-rw-r--r-- | crates/ra_assists/src/assist_config.rs | 5 | ||||
-rw-r--r-- | crates/ra_assists/src/assist_context.rs | 8 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 12 | ||||
-rw-r--r-- | crates/ra_assists/src/tests.rs | 25 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 28 |
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 | ||
7 | use crate::AssistKind; | ||
8 | |||
7 | #[derive(Clone, Debug, PartialEq, Eq)] | 9 | #[derive(Clone, Debug, PartialEq, Eq)] |
8 | pub struct AssistConfig { | 10 | pub struct AssistConfig { |
9 | pub snippet_cap: Option<SnippetCap>, | 11 | pub snippet_cap: Option<SnippetCap>, |
12 | pub allowed: Option<Vec<AssistKind>>, | ||
10 | } | 13 | } |
11 | 14 | ||
12 | impl AssistConfig { | 15 | impl AssistConfig { |
@@ -22,6 +25,6 @@ pub struct SnippetCap { | |||
22 | 25 | ||
23 | impl Default for AssistConfig { | 26 | impl 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 | ||
63 | impl<'a> AssistContext<'a> { | 62 | impl<'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 | ||
792 | pub(crate) fn handle_code_action( | 792 | pub(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, ¶ms, &mut res)?; | 817 | handle_fixes(&snap, ¶ms, &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 | ||
835 | pub(crate) fn handle_resolve_code_action( | 834 | pub(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(¶ms.id, ':').unwrap(); | 851 | let (id_string, index) = split_delim(¶ms.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]; |