diff options
Diffstat (limited to 'crates/ra_assists/src/assist_context.rs')
-rw-r--r-- | crates/ra_assists/src/assist_context.rs | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs index 5b1a4680b..6291c68de 100644 --- a/crates/ra_assists/src/assist_context.rs +++ b/crates/ra_assists/src/assist_context.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use algo::find_covering_element; | 3 | use algo::find_covering_element; |
4 | use hir::Semantics; | 4 | use hir::Semantics; |
5 | use ra_db::{FileId, FileRange}; | 5 | use ra_db::{FileId, FileRange, FilePosition}; |
6 | use ra_fmt::{leading_indent, reindent}; | 6 | use ra_fmt::{leading_indent, reindent}; |
7 | use ra_ide_db::{ | 7 | use ra_ide_db::{ |
8 | source_change::{SourceChange, SourceFileEdit}, | 8 | source_change::{SourceChange, SourceFileEdit}, |
@@ -19,6 +19,7 @@ use crate::{ | |||
19 | assist_config::{AssistConfig, SnippetCap}, | 19 | assist_config::{AssistConfig, SnippetCap}, |
20 | Assist, AssistId, GroupLabel, ResolvedAssist, | 20 | Assist, AssistId, GroupLabel, ResolvedAssist, |
21 | }; | 21 | }; |
22 | use rustc_hash::FxHashMap; | ||
22 | 23 | ||
23 | /// `AssistContext` allows to apply an assist or check if it could be applied. | 24 | /// `AssistContext` allows to apply an assist or check if it could be applied. |
24 | /// | 25 | /// |
@@ -138,6 +139,16 @@ impl Assists { | |||
138 | let label = Assist::new(id, label.into(), None, target); | 139 | let label = Assist::new(id, label.into(), None, target); |
139 | self.add_impl(label, f) | 140 | self.add_impl(label, f) |
140 | } | 141 | } |
142 | pub(crate) fn add_in_multiple_files( | ||
143 | &mut self, | ||
144 | id: AssistId, | ||
145 | label: impl Into<String>, | ||
146 | target: TextRange, | ||
147 | f: impl FnOnce(&mut AssistDirector), | ||
148 | ) -> Option<()> { | ||
149 | let label = Assist::new(id, label.into(), None, target); | ||
150 | self.add_impl_multiple_files(label, f) | ||
151 | } | ||
141 | pub(crate) fn add_group( | 152 | pub(crate) fn add_group( |
142 | &mut self, | 153 | &mut self, |
143 | group: &GroupLabel, | 154 | group: &GroupLabel, |
@@ -162,6 +173,27 @@ impl Assists { | |||
162 | Some(()) | 173 | Some(()) |
163 | } | 174 | } |
164 | 175 | ||
176 | fn add_impl_multiple_files(&mut self, label: Assist, f: impl FnOnce(&mut AssistDirector)) -> Option<()> { | ||
177 | let change_label = label.label.clone(); | ||
178 | if !self.resolve { | ||
179 | return None | ||
180 | } | ||
181 | let mut director = AssistDirector::new(change_label.clone()); | ||
182 | f(&mut director); | ||
183 | let changes = director.finish(); | ||
184 | let file_edits: Vec<SourceFileEdit> = changes.into_iter() | ||
185 | .map(|mut change| change.source_file_edits.pop().unwrap()).collect(); | ||
186 | |||
187 | let source_change = SourceChange { | ||
188 | source_file_edits: file_edits, | ||
189 | file_system_edits: vec![], | ||
190 | is_snippet: false, | ||
191 | }; | ||
192 | |||
193 | self.buf.push((label, Some(source_change))); | ||
194 | Some(()) | ||
195 | } | ||
196 | |||
165 | fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> { | 197 | fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> { |
166 | self.buf.sort_by_key(|(label, _edit)| label.target.len()); | 198 | self.buf.sort_by_key(|(label, _edit)| label.target.len()); |
167 | self.buf | 199 | self.buf |
@@ -255,3 +287,31 @@ impl AssistBuilder { | |||
255 | res | 287 | res |
256 | } | 288 | } |
257 | } | 289 | } |
290 | |||
291 | pub(crate) struct AssistDirector { | ||
292 | source_changes: Vec<SourceChange>, | ||
293 | builders: FxHashMap<FileId, AssistBuilder>, | ||
294 | change_label: String | ||
295 | } | ||
296 | |||
297 | impl AssistDirector { | ||
298 | fn new(change_label: String) -> AssistDirector { | ||
299 | AssistDirector { | ||
300 | source_changes: vec![], | ||
301 | builders: FxHashMap::default(), | ||
302 | change_label | ||
303 | } | ||
304 | } | ||
305 | |||
306 | pub(crate) fn perform(&mut self, file_id: FileId, f: impl FnOnce(&mut AssistBuilder)) { | ||
307 | let mut builder = self.builders.entry(file_id).or_insert(AssistBuilder::new(file_id)); | ||
308 | f(&mut builder); | ||
309 | } | ||
310 | |||
311 | fn finish(mut self) -> Vec<SourceChange> { | ||
312 | for (file_id, builder) in self.builders.into_iter().collect::<Vec<(FileId, AssistBuilder)>>() { | ||
313 | self.source_changes.push(builder.finish()); | ||
314 | } | ||
315 | self.source_changes | ||
316 | } | ||
317 | } | ||