@@ -51,18 +51,28 @@ impl SyntaxEditor {
51
51
}
52
52
53
53
pub fn insert ( & mut self , position : Position , element : impl Element ) {
54
+ debug_assert ! ( is_ancestor_or_self( & position. parent( ) , & self . root) ) ;
54
55
self . changes . push ( Change :: Insert ( position, element. syntax_element ( ) ) )
55
56
}
56
57
57
58
pub fn insert_all ( & mut self , position : Position , elements : Vec < SyntaxElement > ) {
59
+ debug_assert ! ( is_ancestor_or_self( & position. parent( ) , & self . root) ) ;
58
60
self . changes . push ( Change :: InsertAll ( position, elements) )
59
61
}
60
62
61
63
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
+ ) ;
62
70
self . changes . push ( Change :: Replace ( element. syntax_element ( ) , None ) ) ;
63
71
}
64
72
65
73
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) ) ;
66
76
self . changes . push ( Change :: Replace ( old. syntax_element ( ) , Some ( new. syntax_element ( ) ) ) ) ;
67
77
}
68
78
@@ -199,7 +209,10 @@ impl Change {
199
209
fn target_parent ( & self ) -> SyntaxNode {
200
210
match self {
201
211
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 ( ) ,
203
216
}
204
217
}
205
218
@@ -248,6 +261,15 @@ impl Element for SyntaxToken {
248
261
}
249
262
}
250
263
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
+
251
273
#[ cfg( test) ]
252
274
mod tests {
253
275
use expect_test:: expect;
@@ -370,15 +392,11 @@ mod tests {
370
392
Some ( to_wrap. clone ( ) . into ( ) ) ,
371
393
) ;
372
394
373
- // should die:
374
395
editor. replace ( to_replace. syntax ( ) , name_ref. syntax ( ) ) ;
375
396
editor. replace ( to_wrap. syntax ( ) , new_block. syntax ( ) ) ;
376
- // editor.replace(to_replace.syntax(), name_ref.syntax());
377
397
378
398
let edit = editor. finish ( ) ;
379
399
380
- dbg ! ( & edit. annotations) ;
381
-
382
400
let expect = expect ! [ [ r#"
383
401
_ => {
384
402
let var_name = 2 + 2;
@@ -393,4 +411,173 @@ mod tests {
393
411
. flat_map( |( _, elements) | elements)
394
412
. all( |element| element. ancestors( ) . any( |it| & it == edit. root( ) ) ) )
395
413
}
414
+
415
+ #[ test]
416
+ #[ should_panic = "some replace change ranges intersect: [Replace(Node([email protected] ), Some(Node([email protected] ))), Replace(Node([email protected] ), Some(Node([email protected] )))]" ]
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
+ }
396
583
}
0 commit comments