diff options
Diffstat (limited to 'crates/ra_assists/src/assist_context.rs')
-rw-r--r-- | crates/ra_assists/src/assist_context.rs | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs index a680f752b..f3af70a3e 100644 --- a/crates/ra_assists/src/assist_context.rs +++ b/crates/ra_assists/src/assist_context.rs | |||
@@ -15,7 +15,10 @@ use ra_syntax::{ | |||
15 | }; | 15 | }; |
16 | use ra_text_edit::TextEditBuilder; | 16 | use ra_text_edit::TextEditBuilder; |
17 | 17 | ||
18 | use crate::{Assist, AssistId, GroupLabel, ResolvedAssist}; | 18 | use crate::{ |
19 | assist_config::{AssistConfig, SnippetCap}, | ||
20 | Assist, AssistId, GroupLabel, ResolvedAssist, | ||
21 | }; | ||
19 | 22 | ||
20 | /// `AssistContext` allows to apply an assist or check if it could be applied. | 23 | /// `AssistContext` allows to apply an assist or check if it could be applied. |
21 | /// | 24 | /// |
@@ -48,6 +51,7 @@ use crate::{Assist, AssistId, GroupLabel, ResolvedAssist}; | |||
48 | /// moment, because the LSP API is pretty awkward in this place, and it's much | 51 | /// moment, because the LSP API is pretty awkward in this place, and it's much |
49 | /// easier to just compute the edit eagerly :-) | 52 | /// easier to just compute the edit eagerly :-) |
50 | pub(crate) struct AssistContext<'a> { | 53 | pub(crate) struct AssistContext<'a> { |
54 | pub(crate) config: &'a AssistConfig, | ||
51 | pub(crate) sema: Semantics<'a, RootDatabase>, | 55 | pub(crate) sema: Semantics<'a, RootDatabase>, |
52 | pub(crate) db: &'a RootDatabase, | 56 | pub(crate) db: &'a RootDatabase, |
53 | pub(crate) frange: FileRange, | 57 | pub(crate) frange: FileRange, |
@@ -55,10 +59,14 @@ pub(crate) struct AssistContext<'a> { | |||
55 | } | 59 | } |
56 | 60 | ||
57 | impl<'a> AssistContext<'a> { | 61 | impl<'a> AssistContext<'a> { |
58 | pub fn new(sema: Semantics<'a, RootDatabase>, frange: FileRange) -> AssistContext<'a> { | 62 | pub(crate) fn new( |
63 | sema: Semantics<'a, RootDatabase>, | ||
64 | config: &'a AssistConfig, | ||
65 | frange: FileRange, | ||
66 | ) -> AssistContext<'a> { | ||
59 | let source_file = sema.parse(frange.file_id); | 67 | let source_file = sema.parse(frange.file_id); |
60 | let db = sema.db; | 68 | let db = sema.db; |
61 | AssistContext { sema, db, frange, source_file } | 69 | AssistContext { config, sema, db, frange, source_file } |
62 | } | 70 | } |
63 | 71 | ||
64 | // NB, this ignores active selection. | 72 | // NB, this ignores active selection. |
@@ -163,13 +171,13 @@ impl Assists { | |||
163 | 171 | ||
164 | pub(crate) struct AssistBuilder { | 172 | pub(crate) struct AssistBuilder { |
165 | edit: TextEditBuilder, | 173 | edit: TextEditBuilder, |
166 | cursor_position: Option<TextSize>, | ||
167 | file: FileId, | 174 | file: FileId, |
175 | is_snippet: bool, | ||
168 | } | 176 | } |
169 | 177 | ||
170 | impl AssistBuilder { | 178 | impl AssistBuilder { |
171 | pub(crate) fn new(file: FileId) -> AssistBuilder { | 179 | pub(crate) fn new(file: FileId) -> AssistBuilder { |
172 | AssistBuilder { edit: TextEditBuilder::default(), cursor_position: None, file } | 180 | AssistBuilder { edit: TextEditBuilder::default(), file, is_snippet: false } |
173 | } | 181 | } |
174 | 182 | ||
175 | /// Remove specified `range` of text. | 183 | /// Remove specified `range` of text. |
@@ -180,10 +188,30 @@ impl AssistBuilder { | |||
180 | pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) { | 188 | pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) { |
181 | self.edit.insert(offset, text.into()) | 189 | self.edit.insert(offset, text.into()) |
182 | } | 190 | } |
191 | /// Append specified `snippet` at the given `offset` | ||
192 | pub(crate) fn insert_snippet( | ||
193 | &mut self, | ||
194 | _cap: SnippetCap, | ||
195 | offset: TextSize, | ||
196 | snippet: impl Into<String>, | ||
197 | ) { | ||
198 | self.is_snippet = true; | ||
199 | self.insert(offset, snippet); | ||
200 | } | ||
183 | /// Replaces specified `range` of text with a given string. | 201 | /// Replaces specified `range` of text with a given string. |
184 | pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) { | 202 | pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) { |
185 | self.edit.replace(range, replace_with.into()) | 203 | self.edit.replace(range, replace_with.into()) |
186 | } | 204 | } |
205 | /// Replaces specified `range` of text with a given `snippet`. | ||
206 | pub(crate) fn replace_snippet( | ||
207 | &mut self, | ||
208 | _cap: SnippetCap, | ||
209 | range: TextRange, | ||
210 | snippet: impl Into<String>, | ||
211 | ) { | ||
212 | self.is_snippet = true; | ||
213 | self.replace(range, snippet); | ||
214 | } | ||
187 | pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) { | 215 | pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) { |
188 | algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit) | 216 | algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit) |
189 | } | 217 | } |
@@ -207,10 +235,6 @@ impl AssistBuilder { | |||
207 | algo::diff(&node, &new).into_text_edit(&mut self.edit) | 235 | algo::diff(&node, &new).into_text_edit(&mut self.edit) |
208 | } | 236 | } |
209 | 237 | ||
210 | /// Specify desired position of the cursor after the assist is applied. | ||
211 | pub(crate) fn set_cursor(&mut self, offset: TextSize) { | ||
212 | self.cursor_position = Some(offset) | ||
213 | } | ||
214 | // FIXME: better API | 238 | // FIXME: better API |
215 | pub(crate) fn set_file(&mut self, assist_file: FileId) { | 239 | pub(crate) fn set_file(&mut self, assist_file: FileId) { |
216 | self.file = assist_file; | 240 | self.file = assist_file; |
@@ -224,10 +248,10 @@ impl AssistBuilder { | |||
224 | 248 | ||
225 | fn finish(self, change_label: String) -> SourceChange { | 249 | fn finish(self, change_label: String) -> SourceChange { |
226 | let edit = self.edit.finish(); | 250 | let edit = self.edit.finish(); |
227 | if edit.is_empty() && self.cursor_position.is_none() { | 251 | let mut res = SingleFileChange { label: change_label, edit }.into_source_change(self.file); |
228 | panic!("Only call `add_assist` if the assist can be applied") | 252 | if self.is_snippet { |
253 | res.is_snippet = true; | ||
229 | } | 254 | } |
230 | SingleFileChange { label: change_label, edit, cursor_position: self.cursor_position } | 255 | res |
231 | .into_source_change(self.file) | ||
232 | } | 256 | } |
233 | } | 257 | } |