@@ -58,16 +58,27 @@ struct Affected {
58
58
impl Document {
59
59
/// Applies a file change to the document and returns the affected statements
60
60
pub fn apply_file_change ( & mut self , change : & ChangeFileParams ) -> Vec < StatementChange > {
61
+ tracing:: debug!( "apply_file_change: {:?}" , change) ;
61
62
// cleanup all diagnostics with every change because we cannot guarantee that they are still valid
62
63
// this is because we know their ranges only by finding slices within the content which is
63
64
// very much not guaranteed to result in correct ranges
64
65
self . diagnostics . clear ( ) ;
65
66
66
- let changes = change
67
- . changes
68
- . iter ( )
69
- . flat_map ( |c| self . apply_change ( c) )
70
- . collect ( ) ;
67
+ let mut changes = Vec :: new ( ) ;
68
+
69
+ let mut push_back: TextSize = 0 . into ( ) ;
70
+
71
+ for change in & change. changes {
72
+ let change = if push_back > 0 . into ( ) {
73
+ & change. push_back ( push_back)
74
+ } else {
75
+ change
76
+ } ;
77
+
78
+ changes. extend ( self . apply_change ( change) ) ;
79
+
80
+ push_back += change. diff_size ( ) ;
81
+ }
71
82
72
83
self . version = change. version ;
73
84
@@ -1522,6 +1533,38 @@ mod tests {
1522
1533
assert_document_integrity ( & doc) ;
1523
1534
}
1524
1535
1536
+ #[ test]
1537
+ fn multiple_changes_at_once ( ) {
1538
+ let path = PgTPath :: new ( "test.sql" ) ;
1539
+
1540
+ let mut doc = Document :: new ( "\n \n \n \n ALTER TABLE ONLY \" public\" .\" sendout\" \n ADD CONSTRAINT \" sendout_organisation_id_fkey\" FOREIGN
1541
+ KEY (\" organisation_id\" ) REFERENCES \" public\" .\" organisation\" (\" id\" ) ON UPDATE RESTRICT ON DELETE CASCADE;\n " . to_string ( ) , 0 ) ;
1542
+
1543
+ let change = ChangeFileParams {
1544
+ path : path. clone ( ) ,
1545
+ version : 1 ,
1546
+ changes : vec ! [
1547
+ ChangeParams {
1548
+ range: Some ( TextRange :: new( 31 . into( ) , 38 . into( ) ) ) ,
1549
+ text: "omni_channel_message" . to_string( ) ,
1550
+ } ,
1551
+ ChangeParams {
1552
+ range: Some ( TextRange :: new( 60 . into( ) , 67 . into( ) ) ) ,
1553
+ text: "omni_channel_message" . to_string( ) ,
1554
+ } ,
1555
+ ] ,
1556
+ } ;
1557
+
1558
+ let changed = doc. apply_file_change ( & change) ;
1559
+
1560
+ assert_eq ! ( doc. content, "\n \n \n \n ALTER TABLE ONLY \" public\" .\" omni_channel_message\" \n ADD CONSTRAINT \" omni_channel_message_organisation_id_fkey\" FOREIGN
1561
+ KEY (\" organisation_id\" ) REFERENCES \" public\" .\" organisation\" (\" id\" ) ON UPDATE RESTRICT ON DELETE CASCADE;\n " ) ;
1562
+
1563
+ assert_eq ! ( changed. len( ) , 2 ) ;
1564
+
1565
+ assert_document_integrity ( & doc) ;
1566
+ }
1567
+
1525
1568
#[ test]
1526
1569
fn remove_inbetween_whitespace ( ) {
1527
1570
let path = PgTPath :: new ( "test.sql" ) ;
0 commit comments