Add add_placeholder_snippet_group

Used for allowing newly generated syntax constructs to be renamed without having to go through a separate rename step.
This commit is contained in:
DropDemBits 2024-02-15 20:24:31 -05:00
parent b9b0d29b8e
commit 581d457e13
No known key found for this signature in database
GPG key ID: 7FE02A6C1EDFA075

View file

@ -138,7 +138,7 @@ impl SnippetEdit {
.into_iter()
.zip(1..)
.with_position()
.map(|pos| {
.flat_map(|pos| {
let (snippet, index) = match pos {
(itertools::Position::First, it) | (itertools::Position::Middle, it) => it,
// last/only snippet gets index 0
@ -146,11 +146,13 @@ impl SnippetEdit {
| (itertools::Position::Only, (snippet, _)) => (snippet, 0),
};
let range = match snippet {
Snippet::Tabstop(pos) => TextRange::empty(pos),
Snippet::Placeholder(range) => range,
};
(index, range)
match snippet {
Snippet::Tabstop(pos) => vec![(index, TextRange::empty(pos))],
Snippet::Placeholder(range) => vec![(index, range)],
Snippet::PlaceholderGroup(ranges) => {
ranges.into_iter().map(|range| (index, range)).collect()
}
}
})
.collect_vec();
@ -248,7 +250,7 @@ impl SourceChangeBuilder {
fn commit(&mut self) {
let snippet_edit = self.snippet_builder.take().map(|builder| {
SnippetEdit::new(
builder.places.into_iter().map(PlaceSnippet::finalize_position).collect_vec(),
builder.places.into_iter().flat_map(PlaceSnippet::finalize_position).collect(),
)
});
@ -356,6 +358,17 @@ impl SourceChangeBuilder {
self.add_snippet(PlaceSnippet::Over(node.syntax().clone().into()))
}
/// Adds a snippet to move the cursor selected over `nodes`
///
/// This allows for renaming newly generated items without having to go
/// through a separate rename step.
pub fn add_placeholder_snippet_group(&mut self, _cap: SnippetCap, nodes: Vec<SyntaxNode>) {
assert!(nodes.iter().all(|node| node.parent().is_some()));
self.add_snippet(PlaceSnippet::OverGroup(
nodes.into_iter().map(|node| node.into()).collect(),
))
}
fn add_snippet(&mut self, snippet: PlaceSnippet) {
let snippet_builder = self.snippet_builder.get_or_insert(SnippetBuilder { places: vec![] });
snippet_builder.places.push(snippet);
@ -400,6 +413,13 @@ pub enum Snippet {
Tabstop(TextSize),
/// A placeholder snippet (e.g. `${0:placeholder}`).
Placeholder(TextRange),
/// A group of placeholder snippets, e.g.
///
/// ```no_run
/// let ${0:new_var} = 4;
/// fun(1, 2, 3, ${0:new_var});
/// ```
PlaceholderGroup(Vec<TextRange>),
}
enum PlaceSnippet {
@ -409,14 +429,20 @@ enum PlaceSnippet {
After(SyntaxElement),
/// Place a placeholder snippet in place of the element
Over(SyntaxElement),
/// Place a group of placeholder snippets which are linked together
/// in place of the elements
OverGroup(Vec<SyntaxElement>),
}
impl PlaceSnippet {
fn finalize_position(self) -> Snippet {
fn finalize_position(self) -> Vec<Snippet> {
match self {
PlaceSnippet::Before(it) => Snippet::Tabstop(it.text_range().start()),
PlaceSnippet::After(it) => Snippet::Tabstop(it.text_range().end()),
PlaceSnippet::Over(it) => Snippet::Placeholder(it.text_range()),
PlaceSnippet::Before(it) => vec![Snippet::Tabstop(it.text_range().start())],
PlaceSnippet::After(it) => vec![Snippet::Tabstop(it.text_range().end())],
PlaceSnippet::Over(it) => vec![Snippet::Placeholder(it.text_range())],
PlaceSnippet::OverGroup(it) => {
vec![Snippet::PlaceholderGroup(it.into_iter().map(|it| it.text_range()).collect())]
}
}
}
}