aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2020-10-24 19:53:16 +0100
committerLukas Wirth <[email protected]>2020-10-24 19:53:16 +0100
commitaca2735d1e1589dd474858f4cef9ef638d741e5b (patch)
tree25e08ef466ed8b6f023a9f123f1767a253975742
parentd5c294f78ca9c621e38b23102e3b5ca1bdd175f3 (diff)
Support insertion in SyntaxRewriter
-rw-r--r--crates/syntax/src/algo.rs158
1 files changed, 134 insertions, 24 deletions
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs
index 4f9a7a6e8..0baae2f57 100644
--- a/crates/syntax/src/algo.rs
+++ b/crates/syntax/src/algo.rs
@@ -289,11 +289,19 @@ fn _replace_children(
289 with_children(parent, new_children) 289 with_children(parent, new_children)
290} 290}
291 291
292#[derive(Debug, PartialEq, Eq, Hash)]
293enum InsertPos {
294 FirstChildOf(SyntaxNode),
295 Before(SyntaxElement),
296 After(SyntaxElement),
297}
298
292#[derive(Default)] 299#[derive(Default)]
293pub struct SyntaxRewriter<'a> { 300pub struct SyntaxRewriter<'a> {
294 f: Option<Box<dyn Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a>>, 301 f: Option<Box<dyn Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a>>,
295 //FIXME: add debug_assertions that all elements are in fact from the same file. 302 //FIXME: add debug_assertions that all elements are in fact from the same file.
296 replacements: FxHashMap<SyntaxElement, Replacement>, 303 replacements: FxHashMap<SyntaxElement, Replacement>,
304 insertions: IndexMap<InsertPos, Vec<SyntaxElement>>,
297} 305}
298 306
299impl fmt::Debug for SyntaxRewriter<'_> { 307impl fmt::Debug for SyntaxRewriter<'_> {
@@ -304,13 +312,86 @@ impl fmt::Debug for SyntaxRewriter<'_> {
304 312
305impl<'a> SyntaxRewriter<'a> { 313impl<'a> SyntaxRewriter<'a> {
306 pub fn from_fn(f: impl Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a) -> SyntaxRewriter<'a> { 314 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 }
308 } 320 }
309 pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) { 321 pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) {
310 let what = what.clone().into(); 322 let what = what.clone().into();
311 let replacement = Replacement::Delete; 323 let replacement = Replacement::Delete;
312 self.replacements.insert(what, replacement); 324 self.replacements.insert(what, replacement);
313 } 325 }
326 pub fn insert_before<T: Clone + Into<SyntaxElement>, U: Clone + Into<SyntaxElement>>(
327 &mut self,
328 before: &T,
329 what: &U,
330 ) {
331 self.insertions
332 .entry(InsertPos::Before(before.clone().into()))
333 .or_insert_with(Vec::new)
334 .push(what.clone().into());
335 }
336 pub fn insert_after<T: Clone + Into<SyntaxElement>, U: Clone + Into<SyntaxElement>>(
337 &mut self,
338 after: &T,
339 what: &U,
340 ) {
341 self.insertions
342 .entry(InsertPos::After(after.clone().into()))
343 .or_insert_with(Vec::new)
344 .push(what.clone().into());
345 }
346 pub fn insert_as_first_child<T: Clone + Into<SyntaxNode>, U: Clone + Into<SyntaxElement>>(
347 &mut self,
348 parent: &T,
349 what: &U,
350 ) {
351 self.insertions
352 .entry(InsertPos::FirstChildOf(parent.clone().into()))
353 .or_insert_with(Vec::new)
354 .push(what.clone().into());
355 }
356 pub fn insert_many_before<
357 T: Clone + Into<SyntaxElement>,
358 U: IntoIterator<Item = SyntaxElement>,
359 >(
360 &mut self,
361 before: &T,
362 what: U,
363 ) {
364 self.insertions
365 .entry(InsertPos::Before(before.clone().into()))
366 .or_insert_with(Vec::new)
367 .extend(what);
368 }
369 pub fn insert_many_after<
370 T: Clone + Into<SyntaxElement>,
371 U: IntoIterator<Item = SyntaxElement>,
372 >(
373 &mut self,
374 after: &T,
375 what: U,
376 ) {
377 self.insertions
378 .entry(InsertPos::After(after.clone().into()))
379 .or_insert_with(Vec::new)
380 .extend(what);
381 }
382 pub fn insert_many_as_first_children<
383 T: Clone + Into<SyntaxNode>,
384 U: IntoIterator<Item = SyntaxElement>,
385 >(
386 &mut self,
387 parent: &T,
388 what: U,
389 ) {
390 self.insertions
391 .entry(InsertPos::FirstChildOf(parent.clone().into()))
392 .or_insert_with(Vec::new)
393 .extend(what)
394 }
314 pub fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) { 395 pub fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) {
315 let what = what.clone().into(); 396 let what = what.clone().into();
316 let replacement = Replacement::Single(with.clone().into()); 397 let replacement = Replacement::Single(with.clone().into());
@@ -330,7 +411,7 @@ impl<'a> SyntaxRewriter<'a> {
330 } 411 }
331 412
332 pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode { 413 pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode {
333 if self.f.is_none() && self.replacements.is_empty() { 414 if self.f.is_none() && self.replacements.is_empty() && self.insertions.is_empty() {
334 return node.clone(); 415 return node.clone();
335 } 416 }
336 self.rewrite_children(node) 417 self.rewrite_children(node)
@@ -346,14 +427,22 @@ impl<'a> SyntaxRewriter<'a> {
346 /// 427 ///
347 /// Returns `None` when there are no replacements. 428 /// Returns `None` when there are no replacements.
348 pub fn rewrite_root(&self) -> Option<SyntaxNode> { 429 pub fn rewrite_root(&self) -> Option<SyntaxNode> {
430 fn element_to_node_or_parent(element: &SyntaxElement) -> SyntaxNode {
431 match element {
432 SyntaxElement::Node(it) => it.clone(),
433 SyntaxElement::Token(it) => it.parent(),
434 }
435 }
436
349 assert!(self.f.is_none()); 437 assert!(self.f.is_none());
350 self.replacements 438 self.replacements
351 .keys() 439 .keys()
352 .map(|element| match element { 440 .map(element_to_node_or_parent)
353 SyntaxElement::Node(it) => it.clone(), 441 .chain(self.insertions.keys().map(|pos| match pos {
354 SyntaxElement::Token(it) => it.parent(), 442 InsertPos::FirstChildOf(it) => it.clone(),
355 }) 443 InsertPos::Before(it) | InsertPos::After(it) => element_to_node_or_parent(it),
356 // If we only have one replacement, we must return its parent node, since `rewrite` does 444 }))
445 // If we only have one replacement/insertion, we must return its parent node, since `rewrite` does
357 // not replace the node passed to it. 446 // not replace the node passed to it.
358 .map(|it| it.parent().unwrap_or(it)) 447 .map(|it| it.parent().unwrap_or(it))
359 .fold1(|a, b| least_common_ancestor(&a, &b).unwrap()) 448 .fold1(|a, b| least_common_ancestor(&a, &b).unwrap())
@@ -367,9 +456,16 @@ impl<'a> SyntaxRewriter<'a> {
367 self.replacements.get(element).cloned() 456 self.replacements.get(element).cloned()
368 } 457 }
369 458
459 fn insertions(&self, pos: &InsertPos) -> Option<impl Iterator<Item = SyntaxElement> + '_> {
460 self.insertions.get(pos).map(|insertions| insertions.iter().cloned())
461 }
462
370 fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode { 463 fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode {
371 // FIXME: this could be made much faster. 464 // FIXME: this could be made much faster.
372 let mut new_children = Vec::new(); 465 let mut new_children = Vec::new();
466 if let Some(elements) = self.insertions(&InsertPos::FirstChildOf(node.clone())) {
467 new_children.extend(elements.map(element_to_green));
468 }
373 for child in node.children_with_tokens() { 469 for child in node.children_with_tokens() {
374 self.rewrite_self(&mut new_children, &child); 470 self.rewrite_self(&mut new_children, &child);
375 } 471 }
@@ -381,36 +477,50 @@ impl<'a> SyntaxRewriter<'a> {
381 acc: &mut Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>, 477 acc: &mut Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>,
382 element: &SyntaxElement, 478 element: &SyntaxElement,
383 ) { 479 ) {
480 if let Some(elements) = self.insertions(&InsertPos::Before(element.clone())) {
481 acc.extend(elements.map(element_to_green));
482 }
384 if let Some(replacement) = self.replacement(&element) { 483 if let Some(replacement) = self.replacement(&element) {
385 match replacement { 484 match replacement {
386 Replacement::Single(NodeOrToken::Node(it)) => { 485 Replacement::Single(element) => acc.push(element_to_green(element)),
387 acc.push(NodeOrToken::Node(it.green().clone()))
388 }
389 Replacement::Single(NodeOrToken::Token(it)) => {
390 acc.push(NodeOrToken::Token(it.green().clone()))
391 }
392 Replacement::Many(replacements) => { 486 Replacement::Many(replacements) => {
393 acc.extend(replacements.iter().map(|it| match it { 487 acc.extend(replacements.into_iter().map(element_to_green))
394 NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()),
395 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
396 }))
397 } 488 }
398 Replacement::Delete => (), 489 Replacement::Delete => (),
399 }; 490 };
400 return; 491 } else {
492 match element {
493 NodeOrToken::Token(it) => acc.push(NodeOrToken::Token(it.green().clone())),
494 NodeOrToken::Node(it) => {
495 acc.push(NodeOrToken::Node(self.rewrite_children(it).green().clone()));
496 }
497 }
401 } 498 }
402 let res = match element { 499 if let Some(elements) = self.insertions(&InsertPos::After(element.clone())) {
403 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()), 500 acc.extend(elements.map(element_to_green));
404 NodeOrToken::Node(it) => NodeOrToken::Node(self.rewrite_children(it).green().clone()), 501 }
405 }; 502 }
406 acc.push(res) 503}
504
505fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
506 match element {
507 NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()),
508 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
407 } 509 }
408} 510}
409 511
410impl ops::AddAssign for SyntaxRewriter<'_> { 512impl ops::AddAssign for SyntaxRewriter<'_> {
411 fn add_assign(&mut self, rhs: SyntaxRewriter) { 513 fn add_assign(&mut self, rhs: SyntaxRewriter) {
412 assert!(rhs.f.is_none()); 514 assert!(rhs.f.is_none());
413 self.replacements.extend(rhs.replacements) 515 self.replacements.extend(rhs.replacements);
516 for (pos, insertions) in rhs.insertions.into_iter() {
517 match self.insertions.entry(pos) {
518 indexmap::map::Entry::Occupied(mut occupied) => {
519 occupied.get_mut().extend(insertions)
520 }
521 indexmap::map::Entry::Vacant(vacant) => drop(vacant.insert(insertions)),
522 }
523 }
414 } 524 }
415} 525}
416 526