diff options
-rw-r--r-- | crates/ra_assists/src/assist_context.rs | 38 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 31 | ||||
-rw-r--r-- | crates/ra_assists/src/tests.rs | 52 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/src/from_proto.rs | 16 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 34 |
6 files changed, 157 insertions, 20 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs index c33525363..9ca2cfe68 100644 --- a/crates/ra_assists/src/assist_context.rs +++ b/crates/ra_assists/src/assist_context.rs | |||
@@ -19,7 +19,7 @@ use ra_text_edit::TextEditBuilder; | |||
19 | 19 | ||
20 | use crate::{ | 20 | use crate::{ |
21 | assist_config::{AssistConfig, SnippetCap}, | 21 | assist_config::{AssistConfig, SnippetCap}, |
22 | Assist, AssistId, GroupLabel, ResolvedAssist, | 22 | Assist, AssistId, AssistKind, GroupLabel, ResolvedAssist, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | /// `AssistContext` allows to apply an assist or check if it could be applied. | 25 | /// `AssistContext` allows to apply an assist or check if it could be applied. |
@@ -57,6 +57,7 @@ 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>>, | ||
60 | } | 61 | } |
61 | 62 | ||
62 | impl<'a> AssistContext<'a> { | 63 | impl<'a> AssistContext<'a> { |
@@ -64,9 +65,10 @@ impl<'a> AssistContext<'a> { | |||
64 | sema: Semantics<'a, RootDatabase>, | 65 | sema: Semantics<'a, RootDatabase>, |
65 | config: &'a AssistConfig, | 66 | config: &'a AssistConfig, |
66 | frange: FileRange, | 67 | frange: FileRange, |
68 | allowed: Option<Vec<AssistKind>>, | ||
67 | ) -> AssistContext<'a> { | 69 | ) -> AssistContext<'a> { |
68 | let source_file = sema.parse(frange.file_id); | 70 | let source_file = sema.parse(frange.file_id); |
69 | AssistContext { config, sema, frange, source_file } | 71 | AssistContext { config, sema, frange, source_file, allowed } |
70 | } | 72 | } |
71 | 73 | ||
72 | pub(crate) fn db(&self) -> &RootDatabase { | 74 | pub(crate) fn db(&self) -> &RootDatabase { |
@@ -103,14 +105,26 @@ pub(crate) struct Assists { | |||
103 | resolve: bool, | 105 | resolve: bool, |
104 | file: FileId, | 106 | file: FileId, |
105 | buf: Vec<(Assist, Option<SourceChange>)>, | 107 | buf: Vec<(Assist, Option<SourceChange>)>, |
108 | allowed: Option<Vec<AssistKind>>, | ||
106 | } | 109 | } |
107 | 110 | ||
108 | impl Assists { | 111 | impl Assists { |
109 | pub(crate) fn new_resolved(ctx: &AssistContext) -> Assists { | 112 | pub(crate) fn new_resolved(ctx: &AssistContext) -> Assists { |
110 | Assists { resolve: true, file: ctx.frange.file_id, buf: Vec::new() } | 113 | Assists { |
114 | resolve: true, | ||
115 | file: ctx.frange.file_id, | ||
116 | buf: Vec::new(), | ||
117 | allowed: ctx.allowed.clone(), | ||
118 | } | ||
111 | } | 119 | } |
120 | |||
112 | pub(crate) fn new_unresolved(ctx: &AssistContext) -> Assists { | 121 | pub(crate) fn new_unresolved(ctx: &AssistContext) -> Assists { |
113 | Assists { resolve: false, file: ctx.frange.file_id, buf: Vec::new() } | 122 | Assists { |
123 | resolve: false, | ||
124 | file: ctx.frange.file_id, | ||
125 | buf: Vec::new(), | ||
126 | allowed: ctx.allowed.clone(), | ||
127 | } | ||
114 | } | 128 | } |
115 | 129 | ||
116 | pub(crate) fn finish_unresolved(self) -> Vec<Assist> { | 130 | pub(crate) fn finish_unresolved(self) -> Vec<Assist> { |
@@ -139,9 +153,13 @@ impl Assists { | |||
139 | target: TextRange, | 153 | target: TextRange, |
140 | f: impl FnOnce(&mut AssistBuilder), | 154 | f: impl FnOnce(&mut AssistBuilder), |
141 | ) -> Option<()> { | 155 | ) -> Option<()> { |
156 | if !self.is_allowed(&id) { | ||
157 | return None; | ||
158 | } | ||
142 | let label = Assist::new(id, label.into(), None, target); | 159 | let label = Assist::new(id, label.into(), None, target); |
143 | self.add_impl(label, f) | 160 | self.add_impl(label, f) |
144 | } | 161 | } |
162 | |||
145 | pub(crate) fn add_group( | 163 | pub(crate) fn add_group( |
146 | &mut self, | 164 | &mut self, |
147 | group: &GroupLabel, | 165 | group: &GroupLabel, |
@@ -150,9 +168,14 @@ impl Assists { | |||
150 | target: TextRange, | 168 | target: TextRange, |
151 | f: impl FnOnce(&mut AssistBuilder), | 169 | f: impl FnOnce(&mut AssistBuilder), |
152 | ) -> Option<()> { | 170 | ) -> Option<()> { |
171 | if !self.is_allowed(&id) { | ||
172 | return None; | ||
173 | } | ||
174 | |||
153 | let label = Assist::new(id, label.into(), Some(group.clone()), target); | 175 | let label = Assist::new(id, label.into(), Some(group.clone()), target); |
154 | self.add_impl(label, f) | 176 | self.add_impl(label, f) |
155 | } | 177 | } |
178 | |||
156 | fn add_impl(&mut self, label: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> { | 179 | fn add_impl(&mut self, label: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> { |
157 | let source_change = if self.resolve { | 180 | let source_change = if self.resolve { |
158 | let mut builder = AssistBuilder::new(self.file); | 181 | let mut builder = AssistBuilder::new(self.file); |
@@ -170,6 +193,13 @@ impl Assists { | |||
170 | self.buf.sort_by_key(|(label, _edit)| label.target.len()); | 193 | self.buf.sort_by_key(|(label, _edit)| label.target.len()); |
171 | self.buf | 194 | self.buf |
172 | } | 195 | } |
196 | |||
197 | fn is_allowed(&self, id: &AssistId) -> bool { | ||
198 | match &self.allowed { | ||
199 | Some(allowed) => allowed.iter().any(|kind| kind.contains(id.1)), | ||
200 | None => true, | ||
201 | } | ||
202 | } | ||
173 | } | 203 | } |
174 | 204 | ||
175 | pub(crate) struct AssistBuilder { | 205 | pub(crate) struct AssistBuilder { |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 3d61fbded..13a283760 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -37,6 +37,25 @@ pub enum AssistKind { | |||
37 | RefactorRewrite, | 37 | RefactorRewrite, |
38 | } | 38 | } |
39 | 39 | ||
40 | impl AssistKind { | ||
41 | pub fn contains(self, other: AssistKind) -> bool { | ||
42 | if self == other { | ||
43 | return true; | ||
44 | } | ||
45 | |||
46 | match self { | ||
47 | AssistKind::None | AssistKind::Generate => return true, | ||
48 | AssistKind::Refactor => match other { | ||
49 | AssistKind::RefactorExtract | ||
50 | | AssistKind::RefactorInline | ||
51 | | AssistKind::RefactorRewrite => return true, | ||
52 | _ => return false, | ||
53 | }, | ||
54 | _ => return false, | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | |||
40 | /// Unique identifier of the assist, should not be shown to the user | 59 | /// Unique identifier of the assist, should not be shown to the user |
41 | /// directly. | 60 | /// directly. |
42 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 61 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
@@ -67,9 +86,14 @@ impl Assist { | |||
67 | /// | 86 | /// |
68 | /// 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 |
69 | /// returned, without actual edits. | 88 | /// returned, without actual edits. |
70 | pub fn unresolved(db: &RootDatabase, config: &AssistConfig, range: FileRange) -> Vec<Assist> { | 89 | pub fn unresolved( |
90 | db: &RootDatabase, | ||
91 | config: &AssistConfig, | ||
92 | range: FileRange, | ||
93 | allowed: Option<Vec<AssistKind>>, | ||
94 | ) -> Vec<Assist> { | ||
71 | let sema = Semantics::new(db); | 95 | let sema = Semantics::new(db); |
72 | let ctx = AssistContext::new(sema, config, range); | 96 | let ctx = AssistContext::new(sema, config, range, allowed); |
73 | let mut acc = Assists::new_unresolved(&ctx); | 97 | let mut acc = Assists::new_unresolved(&ctx); |
74 | handlers::all().iter().for_each(|handler| { | 98 | handlers::all().iter().for_each(|handler| { |
75 | handler(&mut acc, &ctx); | 99 | handler(&mut acc, &ctx); |
@@ -85,9 +109,10 @@ impl Assist { | |||
85 | db: &RootDatabase, | 109 | db: &RootDatabase, |
86 | config: &AssistConfig, | 110 | config: &AssistConfig, |
87 | range: FileRange, | 111 | range: FileRange, |
112 | allowed: Option<Vec<AssistKind>>, | ||
88 | ) -> Vec<ResolvedAssist> { | 113 | ) -> Vec<ResolvedAssist> { |
89 | let sema = Semantics::new(db); | 114 | let sema = Semantics::new(db); |
90 | let ctx = AssistContext::new(sema, config, range); | 115 | let ctx = AssistContext::new(sema, config, range, allowed); |
91 | let mut acc = Assists::new_resolved(&ctx); | 116 | let mut acc = Assists::new_resolved(&ctx); |
92 | handlers::all().iter().for_each(|handler| { | 117 | handlers::all().iter().for_each(|handler| { |
93 | handler(&mut acc, &ctx); | 118 | handler(&mut acc, &ctx); |
diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs index 858f5ca80..861622d86 100644 --- a/crates/ra_assists/src/tests.rs +++ b/crates/ra_assists/src/tests.rs | |||
@@ -6,7 +6,7 @@ use ra_ide_db::RootDatabase; | |||
6 | use ra_syntax::TextRange; | 6 | use ra_syntax::TextRange; |
7 | use test_utils::{assert_eq_text, extract_offset, extract_range}; | 7 | use test_utils::{assert_eq_text, extract_offset, extract_range}; |
8 | 8 | ||
9 | use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, Assists}; | 9 | use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists}; |
10 | use stdx::trim_indent; | 10 | use stdx::trim_indent; |
11 | 11 | ||
12 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { | 12 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { |
@@ -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) | 38 | let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange, None) |
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) | 45 | Assist::resolved(&db, &AssistConfig::default(), frange, None) |
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); | 76 | let ctx = AssistContext::new(sema, &config, frange, None); |
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); | 108 | let assists = Assist::resolved(&db, &AssistConfig::default(), frange, None); |
109 | let mut assists = assists.iter(); | 109 | let mut assists = assists.iter(); |
110 | 110 | ||
111 | assert_eq!( | 111 | assert_eq!( |
@@ -128,9 +128,49 @@ 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); | 131 | let assists = Assist::resolved(&db, &AssistConfig::default(), frange, None); |
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"); |
135 | assert_eq!(assists.next().expect("expected assist").assist.label, "Replace with match"); | 135 | assert_eq!(assists.next().expect("expected assist").assist.label, "Replace with match"); |
136 | } | 136 | } |
137 | |||
138 | #[test] | ||
139 | fn assist_filter_works() { | ||
140 | let before = " | ||
141 | pub fn test_some_range(a: int) -> bool { | ||
142 | if let 2..6 = <|>5<|> { | ||
143 | true | ||
144 | } else { | ||
145 | false | ||
146 | } | ||
147 | }"; | ||
148 | let (range, before) = extract_range(before); | ||
149 | let (db, file_id) = with_single_file(&before); | ||
150 | let frange = FileRange { file_id, range }; | ||
151 | |||
152 | { | ||
153 | let allowed = Some(vec![AssistKind::Refactor]); | ||
154 | |||
155 | let assists = Assist::resolved(&db, &AssistConfig::default(), frange, allowed); | ||
156 | let mut assists = assists.iter(); | ||
157 | |||
158 | assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable"); | ||
159 | assert_eq!(assists.next().expect("expected assist").assist.label, "Replace with match"); | ||
160 | } | ||
161 | |||
162 | { | ||
163 | let allowed = Some(vec![AssistKind::RefactorExtract]); | ||
164 | let assists = Assist::resolved(&db, &AssistConfig::default(), frange, allowed); | ||
165 | assert_eq!(assists.len(), 1); | ||
166 | |||
167 | let mut assists = assists.iter(); | ||
168 | assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable"); | ||
169 | } | ||
170 | |||
171 | { | ||
172 | let allowed = Some(vec![AssistKind::QuickFix]); | ||
173 | let assists = Assist::resolved(&db, &AssistConfig::default(), frange, allowed); | ||
174 | assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out"); | ||
175 | } | ||
176 | } | ||
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 6a4f5cb3d..c21f2a0b1 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -476,8 +476,9 @@ impl Analysis { | |||
476 | &self, | 476 | &self, |
477 | config: &AssistConfig, | 477 | config: &AssistConfig, |
478 | frange: FileRange, | 478 | frange: FileRange, |
479 | allowed: Option<Vec<AssistKind>>, | ||
479 | ) -> Cancelable<Vec<ResolvedAssist>> { | 480 | ) -> Cancelable<Vec<ResolvedAssist>> { |
480 | self.with_db(|db| ra_assists::Assist::resolved(db, config, frange)) | 481 | self.with_db(|db| ra_assists::Assist::resolved(db, config, frange, allowed)) |
481 | } | 482 | } |
482 | 483 | ||
483 | /// Computes unresolved assists (aka code actions aka intentions) for the given | 484 | /// Computes unresolved assists (aka code actions aka intentions) for the given |
@@ -486,8 +487,9 @@ impl Analysis { | |||
486 | &self, | 487 | &self, |
487 | config: &AssistConfig, | 488 | config: &AssistConfig, |
488 | frange: FileRange, | 489 | frange: FileRange, |
490 | allowed: Option<Vec<AssistKind>>, | ||
489 | ) -> Cancelable<Vec<Assist>> { | 491 | ) -> Cancelable<Vec<Assist>> { |
490 | self.with_db(|db| Assist::unresolved(db, config, frange)) | 492 | self.with_db(|db| Assist::unresolved(db, config, frange, allowed)) |
491 | } | 493 | } |
492 | 494 | ||
493 | /// Computes the set of diagnostics for the given file. | 495 | /// Computes the set of diagnostics for the given file. |
diff --git a/crates/rust-analyzer/src/from_proto.rs b/crates/rust-analyzer/src/from_proto.rs index 15b281103..e2abfa3e0 100644 --- a/crates/rust-analyzer/src/from_proto.rs +++ b/crates/rust-analyzer/src/from_proto.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | use std::convert::TryFrom; | 2 | use std::convert::TryFrom; |
3 | 3 | ||
4 | use ra_db::{FileId, FilePosition, FileRange}; | 4 | use ra_db::{FileId, FilePosition, FileRange}; |
5 | use ra_ide::{LineCol, LineIndex}; | 5 | use ra_ide::{AssistKind, LineCol, LineIndex}; |
6 | use ra_syntax::{TextRange, TextSize}; | 6 | use ra_syntax::{TextRange, TextSize}; |
7 | use vfs::AbsPathBuf; | 7 | use vfs::AbsPathBuf; |
8 | 8 | ||
@@ -52,3 +52,17 @@ pub(crate) fn file_range( | |||
52 | let range = text_range(&line_index, range); | 52 | let range = text_range(&line_index, range); |
53 | Ok(FileRange { file_id, range }) | 53 | Ok(FileRange { file_id, range }) |
54 | } | 54 | } |
55 | |||
56 | pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind> { | ||
57 | let assist_kind = match &kind { | ||
58 | k if k == &lsp_types::CodeActionKind::EMPTY => AssistKind::None, | ||
59 | k if k == &lsp_types::CodeActionKind::QUICKFIX => AssistKind::QuickFix, | ||
60 | k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::Refactor, | ||
61 | k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::RefactorExtract, | ||
62 | k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::RefactorInline, | ||
63 | k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::RefactorRewrite, | ||
64 | _ => return None, | ||
65 | }; | ||
66 | |||
67 | Some(assist_kind) | ||
68 | } | ||
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index f2e24178a..357d5f8ca 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -746,6 +746,19 @@ fn handle_fixes( | |||
746 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 746 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
747 | let line_index = snap.analysis.file_line_index(file_id)?; | 747 | let line_index = snap.analysis.file_line_index(file_id)?; |
748 | let range = from_proto::text_range(&line_index, params.range); | 748 | let range = from_proto::text_range(&line_index, params.range); |
749 | |||
750 | match ¶ms.context.only { | ||
751 | Some(v) => { | ||
752 | if v.iter().any(|it| { | ||
753 | it == &lsp_types::CodeActionKind::EMPTY | ||
754 | || it == &lsp_types::CodeActionKind::QUICKFIX | ||
755 | }) { | ||
756 | return Ok(()); | ||
757 | } | ||
758 | } | ||
759 | None => {} | ||
760 | }; | ||
761 | |||
749 | let diagnostics = snap.analysis.diagnostics(file_id)?; | 762 | let diagnostics = snap.analysis.diagnostics(file_id)?; |
750 | 763 | ||
751 | let fixes_from_diagnostics = diagnostics | 764 | let fixes_from_diagnostics = diagnostics |
@@ -792,18 +805,26 @@ pub(crate) fn handle_code_action( | |||
792 | let line_index = snap.analysis.file_line_index(file_id)?; | 805 | let line_index = snap.analysis.file_line_index(file_id)?; |
793 | let range = from_proto::text_range(&line_index, params.range); | 806 | let range = from_proto::text_range(&line_index, params.range); |
794 | let frange = FileRange { file_id, range }; | 807 | let frange = FileRange { file_id, range }; |
808 | |||
795 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); | 809 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); |
796 | 810 | ||
797 | handle_fixes(&snap, ¶ms, &mut res)?; | 811 | handle_fixes(&snap, ¶ms, &mut res)?; |
798 | 812 | ||
813 | let only = | ||
814 | params.context.only.map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); | ||
815 | |||
799 | if snap.config.client_caps.resolve_code_action { | 816 | if snap.config.client_caps.resolve_code_action { |
800 | for (index, assist) in | 817 | for (index, assist) in snap |
801 | snap.analysis.unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate() | 818 | .analysis |
819 | .unresolved_assists(&snap.config.assist, frange, only)? | ||
820 | .into_iter() | ||
821 | .enumerate() | ||
802 | { | 822 | { |
803 | res.push(to_proto::unresolved_code_action(&snap, assist, index)?); | 823 | res.push(to_proto::unresolved_code_action(&snap, assist, index)?); |
804 | } | 824 | } |
805 | } else { | 825 | } else { |
806 | for assist in snap.analysis.resolved_assists(&snap.config.assist, frange)?.into_iter() { | 826 | for assist in snap.analysis.resolved_assists(&snap.config.assist, frange, only)?.into_iter() |
827 | { | ||
807 | res.push(to_proto::resolved_code_action(&snap, assist)?); | 828 | res.push(to_proto::resolved_code_action(&snap, assist)?); |
808 | } | 829 | } |
809 | } | 830 | } |
@@ -820,8 +841,13 @@ pub(crate) fn handle_resolve_code_action( | |||
820 | let line_index = snap.analysis.file_line_index(file_id)?; | 841 | let line_index = snap.analysis.file_line_index(file_id)?; |
821 | let range = from_proto::text_range(&line_index, params.code_action_params.range); | 842 | let range = from_proto::text_range(&line_index, params.code_action_params.range); |
822 | let frange = FileRange { file_id, range }; | 843 | let frange = FileRange { file_id, range }; |
844 | let only = params | ||
845 | .code_action_params | ||
846 | .context | ||
847 | .only | ||
848 | .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); | ||
823 | 849 | ||
824 | let assists = snap.analysis.resolved_assists(&snap.config.assist, frange)?; | 850 | let assists = snap.analysis.resolved_assists(&snap.config.assist, frange, only)?; |
825 | let (id_string, index) = split_delim(¶ms.id, ':').unwrap(); | 851 | let (id_string, index) = split_delim(¶ms.id, ':').unwrap(); |
826 | let index = index.parse::<usize>().unwrap(); | 852 | let index = index.parse::<usize>().unwrap(); |
827 | let assist = &assists[index]; | 853 | let assist = &assists[index]; |