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