Skip to content

Commit 1a84cad

Browse files
bors[bot]Veykril
andauthored
Merge #6347
6347: Support insertion in SyntaxRewriter r=Veykril a=Veykril Co-authored-by: Lukas Wirth <[email protected]>
2 parents 29f5154 + 45860d5 commit 1a84cad

File tree

1 file changed

+141
-24
lines changed

1 file changed

+141
-24
lines changed

crates/syntax/src/algo.rs

Lines changed: 141 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,19 @@ fn _replace_children(
289289
with_children(parent, new_children)
290290
}
291291

292+
#[derive(Debug, PartialEq, Eq, Hash)]
293+
enum InsertPos {
294+
FirstChildOf(SyntaxNode),
295+
// Before(SyntaxElement),
296+
After(SyntaxElement),
297+
}
298+
292299
#[derive(Default)]
293300
pub struct SyntaxRewriter<'a> {
294301
f: Option<Box<dyn Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a>>,
295302
//FIXME: add debug_assertions that all elements are in fact from the same file.
296303
replacements: FxHashMap<SyntaxElement, Replacement>,
304+
insertions: IndexMap<InsertPos, Vec<SyntaxElement>>,
297305
}
298306

299307
impl fmt::Debug for SyntaxRewriter<'_> {
@@ -304,13 +312,96 @@ impl fmt::Debug for SyntaxRewriter<'_> {
304312

305313
impl<'a> SyntaxRewriter<'a> {
306314
pub fn from_fn(f: impl Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a) -> SyntaxRewriter<'a> {
307-
SyntaxRewriter { f: Some(Box::new(f)), replacements: FxHashMap::default() }
315+
SyntaxRewriter {
316+
f: Some(Box::new(f)),
317+
replacements: FxHashMap::default(),
318+
insertions: IndexMap::default(),
319+
}
308320
}
309321
pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) {
310322
let what = what.clone().into();
311323
let replacement = Replacement::Delete;
312324
self.replacements.insert(what, replacement);
313325
}
326+
pub fn insert_before<T: Clone + Into<SyntaxElement>, U: Clone + Into<SyntaxElement>>(
327+
&mut self,
328+
before: &T,
329+
what: &U,
330+
) {
331+
let before = before.clone().into();
332+
let pos = match before.prev_sibling_or_token() {
333+
Some(sibling) => InsertPos::After(sibling),
334+
None => match before.parent() {
335+
Some(parent) => InsertPos::FirstChildOf(parent),
336+
None => return,
337+
},
338+
};
339+
self.insertions.entry(pos).or_insert_with(Vec::new).push(what.clone().into());
340+
}
341+
pub fn insert_after<T: Clone + Into<SyntaxElement>, U: Clone + Into<SyntaxElement>>(
342+
&mut self,
343+
after: &T,
344+
what: &U,
345+
) {
346+
self.insertions
347+
.entry(InsertPos::After(after.clone().into()))
348+
.or_insert_with(Vec::new)
349+
.push(what.clone().into());
350+
}
351+
pub fn insert_as_first_child<T: Clone + Into<SyntaxNode>, U: Clone + Into<SyntaxElement>>(
352+
&mut self,
353+
parent: &T,
354+
what: &U,
355+
) {
356+
self.insertions
357+
.entry(InsertPos::FirstChildOf(parent.clone().into()))
358+
.or_insert_with(Vec::new)
359+
.push(what.clone().into());
360+
}
361+
pub fn insert_many_before<
362+
T: Clone + Into<SyntaxElement>,
363+
U: IntoIterator<Item = SyntaxElement>,
364+
>(
365+
&mut self,
366+
before: &T,
367+
what: U,
368+
) {
369+
let before = before.clone().into();
370+
let pos = match before.prev_sibling_or_token() {
371+
Some(sibling) => InsertPos::After(sibling),
372+
None => match before.parent() {
373+
Some(parent) => InsertPos::FirstChildOf(parent),
374+
None => return,
375+
},
376+
};
377+
self.insertions.entry(pos).or_insert_with(Vec::new).extend(what);
378+
}
379+
pub fn insert_many_after<
380+
T: Clone + Into<SyntaxElement>,
381+
U: IntoIterator<Item = SyntaxElement>,
382+
>(
383+
&mut self,
384+
after: &T,
385+
what: U,
386+
) {
387+
self.insertions
388+
.entry(InsertPos::After(after.clone().into()))
389+
.or_insert_with(Vec::new)
390+
.extend(what);
391+
}
392+
pub fn insert_many_as_first_children<
393+
T: Clone + Into<SyntaxNode>,
394+
U: IntoIterator<Item = SyntaxElement>,
395+
>(
396+
&mut self,
397+
parent: &T,
398+
what: U,
399+
) {
400+
self.insertions
401+
.entry(InsertPos::FirstChildOf(parent.clone().into()))
402+
.or_insert_with(Vec::new)
403+
.extend(what)
404+
}
314405
pub fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) {
315406
let what = what.clone().into();
316407
let replacement = Replacement::Single(with.clone().into());
@@ -330,7 +421,7 @@ impl<'a> SyntaxRewriter<'a> {
330421
}
331422

332423
pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode {
333-
if self.f.is_none() && self.replacements.is_empty() {
424+
if self.f.is_none() && self.replacements.is_empty() && self.insertions.is_empty() {
334425
return node.clone();
335426
}
336427
self.rewrite_children(node)
@@ -346,14 +437,22 @@ impl<'a> SyntaxRewriter<'a> {
346437
///
347438
/// Returns `None` when there are no replacements.
348439
pub fn rewrite_root(&self) -> Option<SyntaxNode> {
440+
fn element_to_node_or_parent(element: &SyntaxElement) -> SyntaxNode {
441+
match element {
442+
SyntaxElement::Node(it) => it.clone(),
443+
SyntaxElement::Token(it) => it.parent(),
444+
}
445+
}
446+
349447
assert!(self.f.is_none());
350448
self.replacements
351449
.keys()
352-
.map(|element| match element {
353-
SyntaxElement::Node(it) => it.clone(),
354-
SyntaxElement::Token(it) => it.parent(),
355-
})
356-
// If we only have one replacement, we must return its parent node, since `rewrite` does
450+
.map(element_to_node_or_parent)
451+
.chain(self.insertions.keys().map(|pos| match pos {
452+
InsertPos::FirstChildOf(it) => it.clone(),
453+
InsertPos::After(it) => element_to_node_or_parent(it),
454+
}))
455+
// If we only have one replacement/insertion, we must return its parent node, since `rewrite` does
357456
// not replace the node passed to it.
358457
.map(|it| it.parent().unwrap_or(it))
359458
.fold1(|a, b| least_common_ancestor(&a, &b).unwrap())
@@ -367,9 +466,16 @@ impl<'a> SyntaxRewriter<'a> {
367466
self.replacements.get(element).cloned()
368467
}
369468

469+
fn insertions(&self, pos: &InsertPos) -> Option<impl Iterator<Item = SyntaxElement> + '_> {
470+
self.insertions.get(pos).map(|insertions| insertions.iter().cloned())
471+
}
472+
370473
fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode {
371474
// FIXME: this could be made much faster.
372475
let mut new_children = Vec::new();
476+
if let Some(elements) = self.insertions(&InsertPos::FirstChildOf(node.clone())) {
477+
new_children.extend(elements.map(element_to_green));
478+
}
373479
for child in node.children_with_tokens() {
374480
self.rewrite_self(&mut new_children, &child);
375481
}
@@ -383,34 +489,45 @@ impl<'a> SyntaxRewriter<'a> {
383489
) {
384490
if let Some(replacement) = self.replacement(&element) {
385491
match replacement {
386-
Replacement::Single(NodeOrToken::Node(it)) => {
387-
acc.push(NodeOrToken::Node(it.green().clone()))
388-
}
389-
Replacement::Single(NodeOrToken::Token(it)) => {
390-
acc.push(NodeOrToken::Token(it.green().clone()))
391-
}
492+
Replacement::Single(element) => acc.push(element_to_green(element)),
392493
Replacement::Many(replacements) => {
393-
acc.extend(replacements.iter().map(|it| match it {
394-
NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()),
395-
NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
396-
}))
494+
acc.extend(replacements.into_iter().map(element_to_green))
397495
}
398496
Replacement::Delete => (),
399497
};
400-
return;
498+
} else {
499+
match element {
500+
NodeOrToken::Token(it) => acc.push(NodeOrToken::Token(it.green().clone())),
501+
NodeOrToken::Node(it) => {
502+
acc.push(NodeOrToken::Node(self.rewrite_children(it).green().clone()));
503+
}
504+
}
505+
}
506+
if let Some(elements) = self.insertions(&InsertPos::After(element.clone())) {
507+
acc.extend(elements.map(element_to_green));
401508
}
402-
let res = match element {
403-
NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
404-
NodeOrToken::Node(it) => NodeOrToken::Node(self.rewrite_children(it).green().clone()),
405-
};
406-
acc.push(res)
509+
}
510+
}
511+
512+
fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
513+
match element {
514+
NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()),
515+
NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
407516
}
408517
}
409518

410519
impl ops::AddAssign for SyntaxRewriter<'_> {
411520
fn add_assign(&mut self, rhs: SyntaxRewriter) {
412521
assert!(rhs.f.is_none());
413-
self.replacements.extend(rhs.replacements)
522+
self.replacements.extend(rhs.replacements);
523+
for (pos, insertions) in rhs.insertions.into_iter() {
524+
match self.insertions.entry(pos) {
525+
indexmap::map::Entry::Occupied(mut occupied) => {
526+
occupied.get_mut().extend(insertions)
527+
}
528+
indexmap::map::Entry::Vacant(vacant) => drop(vacant.insert(insertions)),
529+
}
530+
}
414531
}
415532
}
416533

0 commit comments

Comments
 (0)