aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/assist_context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/assist_context.rs')
-rw-r--r--crates/ra_assists/src/assist_context.rs60
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};
22use 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
295pub(crate) struct AssistDirector {
296 builders: FxHashMap<FileId, AssistBuilder>,
297}
298
299impl 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
313impl Default for AssistDirector {
314 fn default() -> Self {
315 AssistDirector { builders: FxHashMap::default() }
316 }
317}