1use std::{
8 cell::RefCell,
9 fmt, iter,
10 num::NonZeroU32,
11 ops::RangeInclusive,
12 sync::atomic::{AtomicU32, Ordering},
13};
14
15use rowan::TextRange;
16use rustc_hash::FxHashMap;
17
18use crate::{
19 AstNode, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T,
20 ast::{self, edit::IndentLevel, syntax_factory::SyntaxFactory},
21};
22
23mod edit_algo;
24mod edits;
25mod mapping;
26
27pub use edits::{GetOrCreateWhereClause, Removable};
28pub use mapping::{SyntaxMapping, SyntaxMappingBuilder};
29
30#[derive(Debug)]
31pub struct SyntaxEditor {
32 root: SyntaxNode,
33 changes: RefCell<Vec<Change>>,
34 annotations: RefCell<Vec<(SyntaxElement, SyntaxAnnotation)>>,
35 make: SyntaxFactory,
36}
37
38impl SyntaxEditor {
39 pub fn new(root: SyntaxNode) -> (Self, SyntaxNode) {
46 let mut root = root;
47
48 if root.parent().is_some() || root.is_mutable() {
49 root = root.clone_subtree()
50 };
51
52 let editor = Self {
53 root: root.clone(),
54 changes: RefCell::new(Vec::new()),
55 annotations: RefCell::new(Vec::new()),
56 make: SyntaxFactory::with_mappings(),
57 };
58
59 (editor, root)
60 }
61
62 pub fn with_ast_node<T>(root: &T) -> (Self, T)
64 where
65 T: AstNode,
66 {
67 let (editor, root) = Self::new(root.syntax().clone());
68
69 (editor, T::cast(root).unwrap())
70 }
71
72 pub fn make(&self) -> &SyntaxFactory {
73 &self.make
74 }
75
76 pub fn add_annotation(&self, element: impl Element, annotation: SyntaxAnnotation) {
77 self.annotations.borrow_mut().push((element.syntax_element(), annotation))
78 }
79
80 pub fn add_annotation_all(&self, elements: Vec<impl Element>, annotation: SyntaxAnnotation) {
81 self.annotations
82 .borrow_mut()
83 .extend(elements.into_iter().map(|e| e.syntax_element()).zip(iter::repeat(annotation)));
84 }
85
86 pub fn merge(&self, other: SyntaxEditor) {
87 debug_assert!(
88 self.root == other.root || other.root.ancestors().any(|node| node == self.root),
89 "{:?} is not in the same tree as {:?}",
90 other.root,
91 self.root
92 );
93
94 self.changes.borrow_mut().append(&mut other.changes.into_inner());
95 if let Some(mut m) = self.make.mappings() {
96 m.merge(other.make.take());
97 }
98 self.annotations.borrow_mut().append(&mut other.annotations.into_inner());
99 }
100
101 pub fn insert(&self, position: Position, element: impl Element) {
102 debug_assert!(is_ancestor_or_self(&position.parent(), &self.root));
103 self.changes.borrow_mut().push(Change::Insert(position, element.syntax_element()))
104 }
105
106 pub fn insert_all(&self, position: Position, elements: Vec<SyntaxElement>) {
107 debug_assert!(is_ancestor_or_self(&position.parent(), &self.root));
108 self.changes.borrow_mut().push(Change::InsertAll(position, elements))
109 }
110
111 pub fn insert_with_whitespace(&self, position: Position, element: impl Element) {
112 self.insert_all_with_whitespace(position, vec![element.syntax_element()])
113 }
114
115 pub fn insert_all_with_whitespace(&self, position: Position, mut elements: Vec<SyntaxElement>) {
116 if let Some(first) = elements.first()
117 && let Some(ws) = ws_before(&position, first, &self.make)
118 {
119 elements.insert(0, ws.into());
120 }
121 if let Some(last) = elements.last()
122 && let Some(ws) = ws_after(&position, last, &self.make)
123 {
124 elements.push(ws.into());
125 }
126 self.insert_all(position, elements)
127 }
128
129 pub fn delete(&self, element: impl Element) {
130 let element = element.syntax_element();
131 debug_assert!(is_ancestor_or_self_of_element(&element, &self.root));
132 debug_assert!(
133 !matches!(&element, SyntaxElement::Node(node) if node == &self.root),
134 "should not delete root node"
135 );
136 let mut changes = self.changes.borrow_mut();
137 for change in changes.iter_mut() {
138 if let Change::Replace(existing, replacement) = change
139 && *existing == element
140 {
141 if replacement.is_none() {
142 return;
143 }
144 *replacement = None;
145 return;
146 }
147 }
148 changes.push(Change::Replace(element, None));
149 }
150
151 pub fn delete_all(&self, range: RangeInclusive<SyntaxElement>) {
152 if range.start() == range.end() {
153 self.delete(range.start());
154 return;
155 }
156
157 debug_assert!(is_ancestor_or_self_of_element(range.start(), &self.root));
158 self.changes.borrow_mut().push(Change::ReplaceAll(range, Vec::new()))
159 }
160
161 pub fn replace(&self, old: impl Element, new: impl Element) {
162 let old = old.syntax_element();
163 debug_assert!(is_ancestor_or_self_of_element(&old, &self.root));
164 let new = new.syntax_element();
165 let mut changes = self.changes.borrow_mut();
166 for change in changes.iter_mut() {
167 if let Change::Replace(existing, replacement) = change
168 && *existing == old
169 {
170 match replacement {
171 None => return,
172 Some(existing_new) if *existing_new == new => return,
173 Some(existing_new) => {
174 *existing_new = new;
175 return;
176 }
177 }
178 }
179 }
180 changes.push(Change::Replace(old, Some(new)));
181 }
182
183 pub fn replace_with_many(&self, old: impl Element, new: Vec<SyntaxElement>) {
184 let old = old.syntax_element();
185 debug_assert!(is_ancestor_or_self_of_element(&old, &self.root));
186 debug_assert!(
187 !(matches!(&old, SyntaxElement::Node(node) if node == &self.root) && new.len() > 1),
188 "cannot replace root node with many elements"
189 );
190 self.changes.borrow_mut().push(Change::ReplaceWithMany(old.syntax_element(), new));
191 }
192
193 pub fn replace_all(&self, range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) {
194 if range.start() == range.end() {
195 self.replace_with_many(range.start(), new);
196 return;
197 }
198
199 debug_assert!(is_ancestor_or_self_of_element(range.start(), &self.root));
200 self.changes.borrow_mut().push(Change::ReplaceAll(range, new))
201 }
202
203 pub fn finish(self) -> SyntaxEdit {
204 edit_algo::apply_edits(self)
205 }
206
207 pub fn deleted(&self, element: impl Element) -> bool {
208 let element = element.syntax_element();
209 self.changes
210 .borrow()
211 .iter()
212 .any(|change| matches!(change, Change::Replace(existing, None) if *existing == element))
213 }
214}
215
216pub struct SyntaxEdit {
218 old_root: SyntaxNode,
219 new_root: SyntaxNode,
220 changed_elements: Vec<SyntaxElement>,
221 annotations: FxHashMap<SyntaxAnnotation, Vec<SyntaxElement>>,
222}
223
224impl SyntaxEdit {
225 pub fn old_root(&self) -> &SyntaxNode {
227 &self.old_root
228 }
229
230 pub fn new_root(&self) -> &SyntaxNode {
232 &self.new_root
233 }
234
235 pub fn changed_elements(&self) -> &[SyntaxElement] {
241 self.changed_elements.as_slice()
242 }
243
244 pub fn find_annotation(&self, annotation: SyntaxAnnotation) -> &[SyntaxElement] {
251 self.annotations.get(&annotation).as_ref().map_or(&[], |it| it.as_slice())
252 }
253
254 pub fn find_element(&self, old_node: &SyntaxNode) -> Option<SyntaxNode> {
255 let old_root_start = self.old_root.text_range().start();
256 let old_start = old_node.text_range().start() - old_root_start;
257 let new_root_start = self.new_root.text_range().start();
258 let kind = old_node.kind();
259
260 self.new_root
261 .descendants()
262 .find(|it| it.kind() == kind && it.text_range().start() - new_root_start == old_start)
263 }
264}
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
267#[repr(transparent)]
268pub struct SyntaxAnnotation(NonZeroU32);
269
270impl Default for SyntaxAnnotation {
271 fn default() -> Self {
272 static COUNTER: AtomicU32 = AtomicU32::new(1);
273
274 let id = COUNTER.fetch_add(1, Ordering::Relaxed);
276
277 Self(NonZeroU32::new(id).expect("syntax annotation id overflow"))
278 }
279}
280
281#[derive(Debug)]
283pub struct Position {
284 repr: PositionRepr,
285}
286
287impl Position {
288 pub(crate) fn parent(&self) -> SyntaxNode {
289 self.place().0
290 }
291
292 pub(crate) fn place(&self) -> (SyntaxNode, usize) {
293 match &self.repr {
294 PositionRepr::FirstChild(parent) => (parent.clone(), 0),
295 PositionRepr::After(child) => (child.parent().unwrap(), child.index() + 1),
296 }
297 }
298}
299
300#[derive(Debug)]
301enum PositionRepr {
302 FirstChild(SyntaxNode),
303 After(SyntaxElement),
304}
305
306impl Position {
307 pub fn after(elem: impl Element) -> Position {
308 let repr = PositionRepr::After(elem.syntax_element());
309 Position { repr }
310 }
311
312 pub fn before(elem: impl Element) -> Position {
313 let elem = elem.syntax_element();
314 let repr = match elem.prev_sibling_or_token() {
315 Some(it) => PositionRepr::After(it),
316 None => PositionRepr::FirstChild(elem.parent().unwrap()),
317 };
318 Position { repr }
319 }
320
321 pub fn first_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position {
322 let repr = PositionRepr::FirstChild(node.clone().into());
323 Position { repr }
324 }
325
326 pub fn last_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position {
327 let node = node.clone().into();
328 let repr = match node.last_child_or_token() {
329 Some(it) => PositionRepr::After(it),
330 None => PositionRepr::FirstChild(node),
331 };
332 Position { repr }
333 }
334}
335
336#[derive(Debug)]
337enum Change {
338 Insert(Position, SyntaxElement),
340 InsertAll(Position, Vec<SyntaxElement>),
342 Replace(SyntaxElement, Option<SyntaxElement>),
344 ReplaceWithMany(SyntaxElement, Vec<SyntaxElement>),
346 ReplaceAll(RangeInclusive<SyntaxElement>, Vec<SyntaxElement>),
349}
350
351impl Change {
352 fn target_range(&self) -> TextRange {
353 match self {
354 Change::Insert(target, _) | Change::InsertAll(target, _) => match &target.repr {
355 PositionRepr::FirstChild(parent) => TextRange::at(
356 parent.first_child_or_token().unwrap().text_range().start(),
357 0.into(),
358 ),
359 PositionRepr::After(child) => TextRange::at(child.text_range().end(), 0.into()),
360 },
361 Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => target.text_range(),
362 Change::ReplaceAll(range, _) => {
363 range.start().text_range().cover(range.end().text_range())
364 }
365 }
366 }
367
368 fn target_parent(&self) -> SyntaxNode {
369 match self {
370 Change::Insert(target, _) | Change::InsertAll(target, _) => target.parent(),
371 Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => match target {
372 SyntaxElement::Node(target) => target.parent().unwrap_or_else(|| target.clone()),
373 SyntaxElement::Token(target) => target.parent().unwrap(),
374 },
375 Change::ReplaceAll(target, _) => target.start().parent().unwrap(),
376 }
377 }
378
379 fn change_kind(&self) -> ChangeKind {
380 match self {
381 Change::Insert(_, _) | Change::InsertAll(_, _) => ChangeKind::Insert,
382 Change::Replace(_, _) | Change::ReplaceWithMany(_, _) => ChangeKind::Replace,
383 Change::ReplaceAll(_, _) => ChangeKind::ReplaceRange,
384 }
385 }
386}
387
388#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
389enum ChangeKind {
390 Insert,
391 ReplaceRange,
392 Replace,
393}
394
395impl fmt::Display for Change {
396 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
397 match self {
398 Change::Insert(position, node_or_token) => {
399 let parent = position.parent();
400 let mut parent_str = parent.to_string();
401 let target_range = self.target_range().start() - parent.text_range().start();
402
403 parent_str.insert_str(
404 target_range.into(),
405 &format!("\x1b[42m{node_or_token}\x1b[0m\x1b[K"),
406 );
407 f.write_str(&parent_str)
408 }
409 Change::InsertAll(position, vec) => {
410 let parent = position.parent();
411 let mut parent_str = parent.to_string();
412 let target_range = self.target_range().start() - parent.text_range().start();
413 let insertion: String = vec.iter().map(|it| it.to_string()).collect();
414
415 parent_str
416 .insert_str(target_range.into(), &format!("\x1b[42m{insertion}\x1b[0m\x1b[K"));
417 f.write_str(&parent_str)
418 }
419 Change::Replace(old, new) => {
420 if let Some(new) = new {
421 write!(f, "\x1b[41m{old}\x1b[42m{new}\x1b[0m\x1b[K")
422 } else {
423 write!(f, "\x1b[41m{old}\x1b[0m\x1b[K")
424 }
425 }
426 Change::ReplaceWithMany(old, vec) => {
427 let new: String = vec.iter().map(|it| it.to_string()).collect();
428 write!(f, "\x1b[41m{old}\x1b[42m{new}\x1b[0m\x1b[K")
429 }
430 Change::ReplaceAll(range, vec) => {
431 let parent = range.start().parent().unwrap();
432 let parent_str = parent.to_string();
433 let pre_range =
434 TextRange::new(parent.text_range().start(), range.start().text_range().start());
435 let old_range = TextRange::new(
436 range.start().text_range().start(),
437 range.end().text_range().end(),
438 );
439 let post_range =
440 TextRange::new(range.end().text_range().end(), parent.text_range().end());
441
442 let pre_str = &parent_str[pre_range - parent.text_range().start()];
443 let old_str = &parent_str[old_range - parent.text_range().start()];
444 let post_str = &parent_str[post_range - parent.text_range().start()];
445 let new: String = vec.iter().map(|it| it.to_string()).collect();
446
447 write!(f, "{pre_str}\x1b[41m{old_str}\x1b[42m{new}\x1b[0m\x1b[K{post_str}")
448 }
449 }
450 }
451}
452
453pub trait Element {
456 fn syntax_element(self) -> SyntaxElement;
457}
458
459impl<E: Element + Clone> Element for &'_ E {
460 fn syntax_element(self) -> SyntaxElement {
461 self.clone().syntax_element()
462 }
463}
464
465impl Element for SyntaxElement {
466 fn syntax_element(self) -> SyntaxElement {
467 self
468 }
469}
470
471impl Element for SyntaxNode {
472 fn syntax_element(self) -> SyntaxElement {
473 self.into()
474 }
475}
476
477impl Element for SyntaxToken {
478 fn syntax_element(self) -> SyntaxElement {
479 self.into()
480 }
481}
482
483fn ws_before(
484 position: &Position,
485 new: &SyntaxElement,
486 factory: &SyntaxFactory,
487) -> Option<SyntaxToken> {
488 let prev = match &position.repr {
489 PositionRepr::FirstChild(_) => return None,
490 PositionRepr::After(it) => it,
491 };
492
493 if prev.kind() == T!['{']
494 && new.kind() == SyntaxKind::USE
495 && let Some(item_list) = prev.parent().and_then(ast::ItemList::cast)
496 {
497 let mut indent = IndentLevel::from_element(&item_list.syntax().clone().into());
498 indent.0 += 1;
499 return Some(factory.whitespace(&format!("\n{indent}")));
500 }
501
502 if prev.kind() == T!['{']
503 && ast::Stmt::can_cast(new.kind())
504 && let Some(stmt_list) = prev.parent().and_then(ast::StmtList::cast)
505 {
506 let mut indent = IndentLevel::from_element(&stmt_list.syntax().clone().into());
507 indent.0 += 1;
508 return Some(factory.whitespace(&format!("\n{indent}")));
509 }
510
511 ws_between(prev, new, factory)
512}
513
514fn ws_after(
515 position: &Position,
516 new: &SyntaxElement,
517 factory: &SyntaxFactory,
518) -> Option<SyntaxToken> {
519 let next = match &position.repr {
520 PositionRepr::FirstChild(parent) => parent.first_child_or_token()?,
521 PositionRepr::After(sibling) => sibling.next_sibling_or_token()?,
522 };
523 ws_between(new, &next, factory)
524}
525
526fn ws_between(
527 left: &SyntaxElement,
528 right: &SyntaxElement,
529 factory: &SyntaxFactory,
530) -> Option<SyntaxToken> {
531 if left.kind() == SyntaxKind::WHITESPACE || right.kind() == SyntaxKind::WHITESPACE {
532 return None;
533 }
534 if right.kind() == T![;] || right.kind() == T![,] {
535 return None;
536 }
537 if left.kind() == T![<] || right.kind() == T![>] {
538 return None;
539 }
540 if left.kind() == T![&] && right.kind() == SyntaxKind::LIFETIME {
541 return None;
542 }
543 if right.kind() == SyntaxKind::GENERIC_ARG_LIST {
544 return None;
545 }
546 if right.kind() == SyntaxKind::USE {
547 let mut indent = IndentLevel::from_element(left);
548 if left.kind() == SyntaxKind::USE {
549 indent.0 = IndentLevel::from_element(right).0.max(indent.0);
550 }
551 return Some(factory.whitespace(&format!("\n{indent}")));
552 }
553 if left.kind() == SyntaxKind::ATTR {
554 let mut indent = IndentLevel::from_element(right);
555 if right.kind() == SyntaxKind::ATTR {
556 indent.0 = IndentLevel::from_element(left).0.max(indent.0);
557 }
558 return Some(factory.whitespace(&format!("\n{indent}")));
559 }
560 Some(factory.whitespace(" "))
561}
562
563fn is_ancestor_or_self(node: &SyntaxNode, ancestor: &SyntaxNode) -> bool {
564 node == ancestor || node.ancestors().any(|it| &it == ancestor)
565}
566
567fn is_ancestor_or_self_of_element(node: &SyntaxElement, ancestor: &SyntaxNode) -> bool {
568 matches!(node, SyntaxElement::Node(node) if node == ancestor)
569 || node.ancestors().any(|it| &it == ancestor)
570}
571
572#[cfg(test)]
573mod tests {
574 use expect_test::expect;
575
576 use crate::{
577 AstNode,
578 ast::{self, make},
579 };
580
581 use super::*;
582
583 #[test]
584 fn basic_usage() {
585 let root = make::match_arm(
586 make::wildcard_pat().into(),
587 None,
588 make::expr_tuple([
589 make::expr_bin_op(
590 make::expr_literal("2").into(),
591 ast::BinaryOp::ArithOp(ast::ArithOp::Add),
592 make::expr_literal("2").into(),
593 ),
594 make::expr_literal("true").into(),
595 ])
596 .into(),
597 );
598
599 let (editor, root) = SyntaxEditor::with_ast_node(&root);
600 let make = editor.make();
601
602 let to_wrap = root.syntax().descendants().find_map(ast::TupleExpr::cast).unwrap();
603 let to_replace = root.syntax().descendants().find_map(ast::BinExpr::cast).unwrap();
604
605 let name = make::name("var_name");
606 let name_ref = make::name_ref("var_name").clone_for_update();
607
608 let placeholder_snippet = SyntaxAnnotation::default();
609 editor.add_annotation(name.syntax(), placeholder_snippet);
610 editor.add_annotation(name_ref.syntax(), placeholder_snippet);
611
612 let new_block = make.block_expr(
613 [editor
614 .make()
615 .let_stmt(
616 make.ident_pat(false, false, name.clone()).into(),
617 None,
618 Some(to_replace.clone().into()),
619 )
620 .into()],
621 Some(to_wrap.clone().into()),
622 );
623
624 editor.replace(to_replace.syntax(), name_ref.syntax());
625 editor.replace(to_wrap.syntax(), new_block.syntax());
626
627 let edit = editor.finish();
628
629 let expect = expect![[r#"
630 _ => {
631 let var_name = 2 + 2;
632 (var_name, true)
633 },"#]];
634 expect.assert_eq(&edit.new_root.to_string());
635
636 assert_eq!(edit.find_annotation(placeholder_snippet).len(), 2);
637 assert!(
638 edit.annotations
639 .values()
640 .flatten()
641 .all(|element| element.ancestors().any(|it| &it == edit.new_root()))
642 )
643 }
644
645 #[test]
646 fn test_insert_independent() {
647 let root = make::block_expr(
648 [make::let_stmt(
649 make::ext::simple_ident_pat(make::name("second")).into(),
650 None,
651 Some(make::expr_literal("2").into()),
652 )
653 .into()],
654 None,
655 );
656
657 let (editor, root) = SyntaxEditor::with_ast_node(&root);
658 let make = editor.make();
659 let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap();
660
661 editor.insert(
662 Position::first_child_of(root.stmt_list().unwrap().syntax()),
663 make.let_stmt(
664 make::ext::simple_ident_pat(make::name("first")).into(),
665 None,
666 Some(make::expr_literal("1").into()),
667 )
668 .syntax(),
669 );
670
671 editor.insert(
672 Position::after(second_let.syntax()),
673 make.let_stmt(
674 make::ext::simple_ident_pat(make::name("third")).into(),
675 None,
676 Some(make::expr_literal("3").into()),
677 )
678 .syntax(),
679 );
680
681 let edit = editor.finish();
682
683 let expect = expect![[r#"
684 let first = 1;{
685 let second = 2;let third = 3;
686 }"#]];
687 expect.assert_eq(&edit.new_root.to_string());
688 }
689
690 #[test]
691 fn test_insert_dependent() {
692 let root = make::block_expr(
693 [],
694 Some(
695 make::block_expr(
696 [make::let_stmt(
697 make::ext::simple_ident_pat(make::name("second")).into(),
698 None,
699 Some(make::expr_literal("2").into()),
700 )
701 .into()],
702 None,
703 )
704 .into(),
705 ),
706 );
707
708 let (editor, root) = SyntaxEditor::with_ast_node(&root);
709 let make = editor.make();
710
711 let inner_block =
712 root.syntax().descendants().flat_map(ast::BlockExpr::cast).nth(1).unwrap();
713 let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap();
714
715 let new_block_expr = make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
716
717 let first_let = make.let_stmt(
718 make::ext::simple_ident_pat(make::name("first")).into(),
719 None,
720 Some(make::expr_literal("1").into()),
721 );
722
723 let third_let = make.let_stmt(
724 make::ext::simple_ident_pat(make::name("third")).into(),
725 None,
726 Some(make::expr_literal("3").into()),
727 );
728
729 editor.insert(
730 Position::first_child_of(inner_block.stmt_list().unwrap().syntax()),
731 first_let.syntax(),
732 );
733 editor.insert(Position::after(second_let.syntax()), third_let.syntax());
734 editor.replace(inner_block.syntax(), new_block_expr.syntax());
735
736 let edit = editor.finish();
737
738 let expect = expect![[r#"
739 {
740 {
741 let first = 1;{
742 let second = 2;let third = 3;
743 }
744 }
745 }"#]];
746 expect.assert_eq(&edit.new_root.to_string());
747 }
748
749 #[test]
750 fn test_dependent_change_prefers_nearest_changed_ancestor() {
751 let root = make::block_expr(
752 [],
753 Some(
754 make::block_expr(
755 [make::let_stmt(
756 make::ext::simple_ident_pat(make::name("second")).into(),
757 None,
758 Some(make::expr_literal("2").into()),
759 )
760 .into()],
761 None,
762 )
763 .into(),
764 ),
765 );
766
767 let (editor, root) = SyntaxEditor::with_ast_node(&root);
768 let make = editor.make();
769
770 let inner_block =
771 root.syntax().descendants().flat_map(ast::BlockExpr::cast).nth(1).unwrap();
772
773 let outer_replacement = make.block_expr([], Some(ast::Expr::BlockExpr(root.clone())));
774 let inner_replacement =
775 make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
776
777 let first_let = make.let_stmt(
778 make::ext::simple_ident_pat(make::name("first")).into(),
779 None,
780 Some(make::expr_literal("1").into()),
781 );
782
783 editor.insert(
784 Position::first_child_of(inner_block.stmt_list().unwrap().syntax()),
785 first_let.syntax(),
786 );
787 editor.replace(inner_block.syntax(), inner_replacement.syntax());
788 editor.replace(root.syntax(), outer_replacement.syntax());
789
790 let edit = editor.finish();
791
792 let expect = expect![[r#"
793 {
794 {
795 {
796 let first = 1;{
797 let second = 2;
798 }
799 }
800 }
801 }"#]];
802 expect.assert_eq(&edit.new_root.to_string());
803 }
804
805 #[test]
806 fn test_replace_root_with_dependent() {
807 let root = make::block_expr(
808 [make::let_stmt(
809 make::ext::simple_ident_pat(make::name("second")).into(),
810 None,
811 Some(make::expr_literal("2").into()),
812 )
813 .into()],
814 None,
815 );
816
817 let (editor, root) = SyntaxEditor::with_ast_node(&root);
818 let make = editor.make();
819
820 let inner_block = root;
821
822 let new_block_expr = make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
823
824 let first_let = make.let_stmt(
825 make::ext::simple_ident_pat(make::name("first")).into(),
826 None,
827 Some(make::expr_literal("1").into()),
828 );
829
830 editor.insert(
831 Position::first_child_of(inner_block.stmt_list().unwrap().syntax()),
832 first_let.syntax(),
833 );
834 editor.replace(inner_block.syntax(), new_block_expr.syntax());
835
836 let edit = editor.finish();
837
838 let expect = expect![[r#"
839 {
840 let first = 1;{
841 let second = 2;
842 }
843 }"#]];
844 expect.assert_eq(&edit.new_root.to_string());
845 }
846
847 #[test]
848 fn test_replace_token_in_parent() {
849 let parent_fn = make::fn_(
850 None,
851 None,
852 make::name("it"),
853 None,
854 None,
855 make::param_list(None, []),
856 make::block_expr([], Some(make::ext::expr_unit())),
857 Some(make::ret_type(make::ty_unit())),
858 false,
859 false,
860 false,
861 false,
862 );
863
864 let (editor, parent_fn) = SyntaxEditor::with_ast_node(&parent_fn);
865
866 if let Some(ret_ty) = parent_fn.ret_type() {
867 editor.delete(ret_ty.syntax().clone());
868
869 if let Some(SyntaxElement::Token(token)) = ret_ty.syntax().next_sibling_or_token()
870 && token.kind().is_trivia()
871 {
872 editor.delete(token);
873 }
874 }
875
876 if let Some(tail) = parent_fn.body().unwrap().tail_expr() {
877 editor.delete(tail.syntax().clone());
878 }
879
880 let edit = editor.finish();
881
882 let expect = expect![["fn it() {\n \n}"]];
883 expect.assert_eq(&edit.new_root.to_string());
884 }
885
886 #[test]
887 fn test_more_times_replace_node_to_mutable_token() {
888 let arg_list =
889 make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
890
891 let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
892
893 let target_expr = make::token(parser::SyntaxKind::UNDERSCORE);
894
895 for arg in arg_list.args() {
896 editor.replace(arg.syntax(), &target_expr);
897 }
898
899 let edit = editor.finish();
900
901 let expect = expect![["(_, _)"]];
902 expect.assert_eq(&edit.new_root.to_string());
903 }
904
905 #[test]
906 fn test_more_times_replace_node_to_mutable() {
907 let arg_list =
908 make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
909
910 let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
911
912 let target_expr = make::expr_literal("3").clone_for_update();
913
914 for arg in arg_list.args() {
915 editor.replace(arg.syntax(), target_expr.syntax());
916 }
917
918 let edit = editor.finish();
919
920 let expect = expect![["(3, 3)"]];
921 expect.assert_eq(&edit.new_root.to_string());
922 }
923
924 #[test]
925 fn test_more_times_insert_node_to_mutable() {
926 let arg_list =
927 make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
928
929 let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
930
931 let target_expr = make::ext::expr_unit().clone_for_update();
932
933 for arg in arg_list.args() {
934 editor.insert(Position::before(arg.syntax()), target_expr.syntax());
935 }
936
937 let edit = editor.finish();
938
939 let expect = expect![["(()1, ()2)"]];
940 expect.assert_eq(&edit.new_root.to_string());
941 }
942}