Skip to content

Commit 3a7c218

Browse files
bors[bot]mcrakhman
andauthored
Merge #4576
4576: Add implementation of extract struct from enum variant r=matklad a=mcrakhman Hi guys! I implemented the extraction functionality including modifying multiple files. The only thing I didn't change the cursor position. I've done it with a previous API, but now snippets have been introduced and I need to figure out how to do it. Please bear in mind that I am a newcomer in the rust-analyzer (and also Rust) world, so I tried to implement the feature to the best of my knowledge, but the API is very new to me, so I am very welcome to introducing changes etc. Co-authored-by: Mikhail Rakhmanov <rakhmanov.m@gmail.com>
2 parents 38ac331 + 5dda995 commit 3a7c218

File tree

4 files changed

+403
-0
lines changed

4 files changed

+403
-0
lines changed

crates/ra_assists/src/assist_context.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::{
1919
assist_config::{AssistConfig, SnippetCap},
2020
Assist, AssistId, GroupLabel, ResolvedAssist,
2121
};
22+
use rustc_hash::FxHashMap;
2223

2324
/// `AssistContext` allows to apply an assist or check if it could be applied.
2425
///
@@ -138,6 +139,16 @@ impl Assists {
138139
let label = Assist::new(id, label.into(), None, target);
139140
self.add_impl(label, f)
140141
}
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+
}
141152
pub(crate) fn add_group(
142153
&mut self,
143154
group: &GroupLabel,
@@ -162,6 +173,31 @@ impl Assists {
162173
Some(())
163174
}
164175

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+
165201
fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> {
166202
self.buf.sort_by_key(|(label, _edit)| label.target.len());
167203
self.buf
@@ -255,3 +291,27 @@ impl AssistBuilder {
255291
res
256292
}
257293
}
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+
}

0 commit comments

Comments
 (0)