diff options
Diffstat (limited to 'crates/ra_assists/src/assist_context.rs')
-rw-r--r-- | crates/ra_assists/src/assist_context.rs | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs index a680f752b..005c17776 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. |
@@ -165,11 +173,17 @@ pub(crate) struct AssistBuilder { | |||
165 | edit: TextEditBuilder, | 173 | edit: TextEditBuilder, |
166 | cursor_position: Option<TextSize>, | 174 | cursor_position: Option<TextSize>, |
167 | file: FileId, | 175 | file: FileId, |
176 | is_snippet: bool, | ||
168 | } | 177 | } |
169 | 178 | ||
170 | impl AssistBuilder { | 179 | impl AssistBuilder { |
171 | pub(crate) fn new(file: FileId) -> AssistBuilder { | 180 | pub(crate) fn new(file: FileId) -> AssistBuilder { |
172 | AssistBuilder { edit: TextEditBuilder::default(), cursor_position: None, file } | 181 | AssistBuilder { |
182 | edit: TextEditBuilder::default(), | ||
183 | cursor_position: None, | ||
184 | file, | ||
185 | is_snippet: false, | ||
186 | } | ||
173 | } | 187 | } |
174 | 188 | ||
175 | /// Remove specified `range` of text. | 189 | /// Remove specified `range` of text. |
@@ -180,10 +194,30 @@ impl AssistBuilder { | |||
180 | pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) { | 194 | pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) { |
181 | self.edit.insert(offset, text.into()) | 195 | self.edit.insert(offset, text.into()) |
182 | } | 196 | } |
197 | /// Append specified `snippet` at the given `offset` | ||
198 | pub(crate) fn insert_snippet( | ||
199 | &mut self, | ||
200 | _cap: SnippetCap, | ||
201 | offset: TextSize, | ||
202 | snippet: impl Into<String>, | ||
203 | ) { | ||
204 | self.is_snippet = true; | ||
205 | self.insert(offset, snippet); | ||
206 | } | ||
183 | /// Replaces specified `range` of text with a given string. | 207 | /// Replaces specified `range` of text with a given string. |
184 | pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) { | 208 | pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) { |
185 | self.edit.replace(range, replace_with.into()) | 209 | self.edit.replace(range, replace_with.into()) |
186 | } | 210 | } |
211 | /// Replaces specified `range` of text with a given `snippet`. | ||
212 | pub(crate) fn replace_snippet( | ||
213 | &mut self, | ||
214 | _cap: SnippetCap, | ||
215 | range: TextRange, | ||
216 | snippet: impl Into<String>, | ||
217 | ) { | ||
218 | self.is_snippet = true; | ||
219 | self.replace(range, snippet); | ||
220 | } | ||
187 | pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) { | 221 | 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) | 222 | algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit) |
189 | } | 223 | } |
@@ -227,7 +261,12 @@ impl AssistBuilder { | |||
227 | if edit.is_empty() && self.cursor_position.is_none() { | 261 | if edit.is_empty() && self.cursor_position.is_none() { |
228 | panic!("Only call `add_assist` if the assist can be applied") | 262 | panic!("Only call `add_assist` if the assist can be applied") |
229 | } | 263 | } |
230 | SingleFileChange { label: change_label, edit, cursor_position: self.cursor_position } | 264 | let mut res = |
231 | .into_source_change(self.file) | 265 | SingleFileChange { label: change_label, edit, cursor_position: self.cursor_position } |
266 | .into_source_change(self.file); | ||
267 | if self.is_snippet { | ||
268 | res.is_snippet = true; | ||
269 | } | ||
270 | res | ||
232 | } | 271 | } |
233 | } | 272 | } |