@@ -51,18 +51,28 @@ impl SyntaxEditor {
5151 }
5252
5353 pub fn insert ( & mut self , position : Position , element : impl Element ) {
54+ debug_assert ! ( is_ancestor_or_self( & position. parent( ) , & self . root) ) ;
5455 self . changes . push ( Change :: Insert ( position, element. syntax_element ( ) ) )
5556 }
5657
5758 pub fn insert_all ( & mut self , position : Position , elements : Vec < SyntaxElement > ) {
59+ debug_assert ! ( is_ancestor_or_self( & position. parent( ) , & self . root) ) ;
5860 self . changes . push ( Change :: InsertAll ( position, elements) )
5961 }
6062
6163 pub fn delete ( & mut self , element : impl Element ) {
64+ let element = element. syntax_element ( ) ;
65+ debug_assert ! ( is_ancestor_or_self_of_element( & element, & self . root) ) ;
66+ debug_assert ! (
67+ !matches!( & element, SyntaxElement :: Node ( node) if node == & self . root) ,
68+ "should not delete root node"
69+ ) ;
6270 self . changes . push ( Change :: Replace ( element. syntax_element ( ) , None ) ) ;
6371 }
6472
6573 pub fn replace ( & mut self , old : impl Element , new : impl Element ) {
74+ let old = old. syntax_element ( ) ;
75+ debug_assert ! ( is_ancestor_or_self_of_element( & old, & self . root) ) ;
6676 self . changes . push ( Change :: Replace ( old. syntax_element ( ) , Some ( new. syntax_element ( ) ) ) ) ;
6777 }
6878
@@ -199,7 +209,10 @@ impl Change {
199209 fn target_parent ( & self ) -> SyntaxNode {
200210 match self {
201211 Change :: Insert ( target, _) | Change :: InsertAll ( target, _) => target. parent ( ) ,
202- Change :: Replace ( target, _) => target. parent ( ) . unwrap ( ) ,
212+ Change :: Replace ( SyntaxElement :: Node ( target) , _) => {
213+ target. parent ( ) . unwrap_or_else ( || target. clone ( ) )
214+ }
215+ Change :: Replace ( SyntaxElement :: Token ( target) , _) => target. parent ( ) . unwrap ( ) ,
203216 }
204217 }
205218
@@ -248,6 +261,15 @@ impl Element for SyntaxToken {
248261 }
249262}
250263
264+ fn is_ancestor_or_self ( node : & SyntaxNode , ancestor : & SyntaxNode ) -> bool {
265+ node == ancestor || node. ancestors ( ) . any ( |it| & it == ancestor)
266+ }
267+
268+ fn is_ancestor_or_self_of_element ( node : & SyntaxElement , ancestor : & SyntaxNode ) -> bool {
269+ matches ! ( node, SyntaxElement :: Node ( node) if node == ancestor)
270+ || node. ancestors ( ) . any ( |it| & it == ancestor)
271+ }
272+
251273#[ cfg( test) ]
252274mod tests {
253275 use expect_test:: expect;
@@ -370,15 +392,11 @@ mod tests {
370392 Some ( to_wrap. clone ( ) . into ( ) ) ,
371393 ) ;
372394
373- // should die:
374395 editor. replace ( to_replace. syntax ( ) , name_ref. syntax ( ) ) ;
375396 editor. replace ( to_wrap. syntax ( ) , new_block. syntax ( ) ) ;
376- // editor.replace(to_replace.syntax(), name_ref.syntax());
377397
378398 let edit = editor. finish ( ) ;
379399
380- dbg ! ( & edit. annotations) ;
381-
382400 let expect = expect ! [ [ r#"
383401 _ => {
384402 let var_name = 2 + 2;
@@ -393,4 +411,173 @@ mod tests {
393411 . flat_map( |( _, elements) | elements)
394412 . all( |element| element. ancestors( ) . any( |it| & it == edit. root( ) ) ) )
395413 }
414+
415+ #[ test]
416+ #[ should_panic = "some replace change ranges intersect: [Replace(Node(TUPLE_EXPR@5..7), Some(Node(NAME_REF@0..8))), Replace(Node(TUPLE_EXPR@5..7), Some(Node(NAME_REF@0..8)))]" ]
417+ fn fail_on_non_disjoint_single_replace ( ) {
418+ let root = make:: match_arm ( [ make:: wildcard_pat ( ) . into ( ) ] , None , make:: expr_tuple ( [ ] ) ) ;
419+
420+ let to_wrap = root. syntax ( ) . descendants ( ) . find_map ( ast:: TupleExpr :: cast) . unwrap ( ) ;
421+
422+ let mut editor = SyntaxEditor :: new ( root. syntax ( ) . clone ( ) ) ;
423+
424+ let name_ref = make:: name_ref ( "var_name" ) . clone_for_update ( ) ;
425+
426+ // should die, ranges are not disjoint
427+ editor. replace ( to_wrap. syntax ( ) , name_ref. syntax ( ) ) ;
428+ editor. replace ( to_wrap. syntax ( ) , name_ref. syntax ( ) ) ;
429+
430+ let _ = editor. finish ( ) ;
431+ }
432+
433+ #[ test]
434+ fn test_insert_independent ( ) {
435+ let root = make:: block_expr (
436+ [ make:: let_stmt (
437+ make:: ext:: simple_ident_pat ( make:: name ( "second" ) ) . into ( ) ,
438+ None ,
439+ Some ( make:: expr_literal ( "2" ) . into ( ) ) ,
440+ )
441+ . into ( ) ] ,
442+ None ,
443+ ) ;
444+
445+ let second_let = root. syntax ( ) . descendants ( ) . find_map ( ast:: LetStmt :: cast) . unwrap ( ) ;
446+
447+ let mut editor = SyntaxEditor :: new ( root. syntax ( ) . clone ( ) ) ;
448+
449+ editor. insert (
450+ Position :: first_child_of ( root. stmt_list ( ) . unwrap ( ) . syntax ( ) ) ,
451+ make_let_stmt (
452+ None ,
453+ make:: ext:: simple_ident_pat ( make:: name ( "first" ) ) . into ( ) ,
454+ None ,
455+ Some ( make:: expr_literal ( "1" ) . into ( ) ) ,
456+ )
457+ . syntax ( ) ,
458+ ) ;
459+
460+ editor. insert (
461+ Position :: after ( second_let. syntax ( ) ) ,
462+ make_let_stmt (
463+ None ,
464+ make:: ext:: simple_ident_pat ( make:: name ( "third" ) ) . into ( ) ,
465+ None ,
466+ Some ( make:: expr_literal ( "3" ) . into ( ) ) ,
467+ )
468+ . syntax ( ) ,
469+ ) ;
470+
471+ let edit = editor. finish ( ) ;
472+
473+ let expect = expect ! [ [ r#"
474+ let first = 1;{
475+ let second = 2;let third = 3;
476+ }"# ] ] ;
477+ expect. assert_eq ( & edit. root . to_string ( ) ) ;
478+ }
479+
480+ #[ test]
481+ fn test_insert_dependent ( ) {
482+ let root = make:: block_expr (
483+ [ ] ,
484+ Some (
485+ make:: block_expr (
486+ [ make:: let_stmt (
487+ make:: ext:: simple_ident_pat ( make:: name ( "second" ) ) . into ( ) ,
488+ None ,
489+ Some ( make:: expr_literal ( "2" ) . into ( ) ) ,
490+ )
491+ . into ( ) ] ,
492+ None ,
493+ )
494+ . into ( ) ,
495+ ) ,
496+ ) ;
497+
498+ let inner_block =
499+ root. syntax ( ) . descendants ( ) . flat_map ( ast:: BlockExpr :: cast) . nth ( 1 ) . unwrap ( ) ;
500+ let second_let = root. syntax ( ) . descendants ( ) . find_map ( ast:: LetStmt :: cast) . unwrap ( ) ;
501+
502+ let mut editor = SyntaxEditor :: new ( root. syntax ( ) . clone ( ) ) ;
503+
504+ let new_block_expr =
505+ make_block_expr ( Some ( & mut editor) , [ ] , Some ( ast:: Expr :: BlockExpr ( inner_block. clone ( ) ) ) ) ;
506+
507+ let first_let = make_let_stmt (
508+ Some ( & mut editor) ,
509+ make:: ext:: simple_ident_pat ( make:: name ( "first" ) ) . into ( ) ,
510+ None ,
511+ Some ( make:: expr_literal ( "1" ) . into ( ) ) ,
512+ ) ;
513+
514+ let third_let = make_let_stmt (
515+ Some ( & mut editor) ,
516+ make:: ext:: simple_ident_pat ( make:: name ( "third" ) ) . into ( ) ,
517+ None ,
518+ Some ( make:: expr_literal ( "3" ) . into ( ) ) ,
519+ ) ;
520+
521+ editor. insert (
522+ Position :: first_child_of ( inner_block. stmt_list ( ) . unwrap ( ) . syntax ( ) ) ,
523+ first_let. syntax ( ) ,
524+ ) ;
525+ editor. insert ( Position :: after ( second_let. syntax ( ) ) , third_let. syntax ( ) ) ;
526+ editor. replace ( inner_block. syntax ( ) , new_block_expr. syntax ( ) ) ;
527+
528+ let edit = editor. finish ( ) ;
529+
530+ let expect = expect ! [ [ r#"
531+ {
532+ {
533+ let first = 1;{
534+ let second = 2;let third = 3;
535+ }
536+ }
537+ }"# ] ] ;
538+ expect. assert_eq ( & edit. root . to_string ( ) ) ;
539+ }
540+
541+ #[ test]
542+ fn test_replace_root_with_dependent ( ) {
543+ let root = make:: block_expr (
544+ [ make:: let_stmt (
545+ make:: ext:: simple_ident_pat ( make:: name ( "second" ) ) . into ( ) ,
546+ None ,
547+ Some ( make:: expr_literal ( "2" ) . into ( ) ) ,
548+ )
549+ . into ( ) ] ,
550+ None ,
551+ ) ;
552+
553+ let inner_block = root. clone ( ) ;
554+
555+ let mut editor = SyntaxEditor :: new ( root. syntax ( ) . clone ( ) ) ;
556+
557+ let new_block_expr =
558+ make_block_expr ( Some ( & mut editor) , [ ] , Some ( ast:: Expr :: BlockExpr ( inner_block. clone ( ) ) ) ) ;
559+
560+ let first_let = make_let_stmt (
561+ Some ( & mut editor) ,
562+ make:: ext:: simple_ident_pat ( make:: name ( "first" ) ) . into ( ) ,
563+ None ,
564+ Some ( make:: expr_literal ( "1" ) . into ( ) ) ,
565+ ) ;
566+
567+ editor. insert (
568+ Position :: first_child_of ( inner_block. stmt_list ( ) . unwrap ( ) . syntax ( ) ) ,
569+ first_let. syntax ( ) ,
570+ ) ;
571+ editor. replace ( inner_block. syntax ( ) , new_block_expr. syntax ( ) ) ;
572+
573+ let edit = editor. finish ( ) ;
574+
575+ let expect = expect ! [ [ r#"
576+ {
577+ let first = 1;{
578+ let second = 2;
579+ }
580+ }"# ] ] ;
581+ expect. assert_eq ( & edit. root . to_string ( ) ) ;
582+ }
396583}
0 commit comments