diff options
Diffstat (limited to 'crates/ra_assists/src/assist_context.rs')
-rw-r--r-- | crates/ra_assists/src/assist_context.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs index 5b1a4680b..1925db8b2 100644 --- a/crates/ra_assists/src/assist_context.rs +++ b/crates/ra_assists/src/assist_context.rs | |||
@@ -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,31 @@ impl Assists { | |||
162 | Some(()) | 173 | Some(()) |
163 | } | 174 | } |
164 | 175 | ||
176 | fn add_impl_multiple_files( | ||
177 | &mut self, | ||
178 | label: Assist, | ||
179 | f: impl FnOnce(&mut AssistDirector), | ||
180 | ) -> Option<()> { | ||
181 | if !self.resolve { | ||
182 | self.buf.push((label, None)); | ||
183 | return None; | ||
184 | } | ||
185 | let mut director = AssistDirector::default(); | ||
186 | f(&mut director); | ||
187 | let changes = director.finish(); | ||
188 | let file_edits: Vec<SourceFileEdit> = | ||
189 | changes.into_iter().map(|mut change| change.source_file_edits.pop().unwrap()).collect(); | ||
190 | |||
191 | let source_change = SourceChange { | ||
192 | source_file_edits: file_edits, | ||
193 | file_system_edits: vec![], | ||
194 | is_snippet: false, | ||
195 | }; | ||
196 | |||
197 | self.buf.push((label, Some(source_change))); | ||
198 | Some(()) | ||
199 | } | ||
200 | |||
165 | fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> { | 201 | fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> { |
166 | self.buf.sort_by_key(|(label, _edit)| label.target.len()); | 202 | self.buf.sort_by_key(|(label, _edit)| label.target.len()); |
167 | self.buf | 203 | self.buf |
@@ -255,3 +291,27 @@ impl AssistBuilder { | |||
255 | res | 291 | res |
256 | } | 292 | } |
257 | } | 293 | } |
294 | |||
295 | pub(crate) struct AssistDirector { | ||
296 | builders: FxHashMap<FileId, AssistBuilder>, | ||
297 | } | ||
298 | |||
299 | impl AssistDirector { | ||
300 | pub(crate) fn perform(&mut self, file_id: FileId, f: impl FnOnce(&mut AssistBuilder)) { | ||
301 | let mut builder = self.builders.entry(file_id).or_insert(AssistBuilder::new(file_id)); | ||
302 | f(&mut builder); | ||
303 | } | ||
304 | |||
305 | fn finish(self) -> Vec<SourceChange> { | ||
306 | self.builders | ||
307 | .into_iter() | ||
308 | .map(|(_, builder)| builder.finish()) | ||
309 | .collect::<Vec<SourceChange>>() | ||
310 | } | ||
311 | } | ||
312 | |||
313 | impl Default for AssistDirector { | ||
314 | fn default() -> Self { | ||
315 | AssistDirector { builders: FxHashMap::default() } | ||
316 | } | ||
317 | } | ||