@@ -294,7 +294,10 @@ impl Document {
294
294
new_stmt_text : changed_content[ new_ranges[ 0 ] ] . to_string ( ) ,
295
295
// change must be relative to the statement
296
296
change_text : change. text . clone ( ) ,
297
- change_range : change_range. sub ( old_range. start ( ) ) ,
297
+ // make sure we always have a valid range >= 0
298
+ change_range : change_range
299
+ . checked_sub ( old_range. start ( ) )
300
+ . unwrap_or ( change_range. sub ( change_range. start ( ) ) ) ,
298
301
} ) ) ;
299
302
}
300
303
@@ -931,6 +934,46 @@ mod tests {
931
934
assert_document_integrity ( & d) ;
932
935
}
933
936
937
+ #[ test]
938
+ fn removing_newline_at_the_beginning ( ) {
939
+ let path = PgLTPath :: new ( "test.sql" ) ;
940
+ let input = "\n " ;
941
+
942
+ let mut d = Document :: new ( path. clone ( ) , input. to_string ( ) , 1 ) ;
943
+
944
+ assert_eq ! ( d. positions. len( ) , 0 ) ;
945
+
946
+ let change = ChangeFileParams {
947
+ path : path. clone ( ) ,
948
+ version : 2 ,
949
+ changes : vec ! [ ChangeParams {
950
+ text: "\n begin;\n \n select 1\n \n rollback;\n " . to_string( ) ,
951
+ range: Some ( TextRange :: new( 0 . into( ) , 1 . into( ) ) ) ,
952
+ } ] ,
953
+ } ;
954
+
955
+ let changes = d. apply_file_change ( & change) ;
956
+
957
+ assert_eq ! ( changes. len( ) , 3 ) ;
958
+
959
+ assert_document_integrity ( & d) ;
960
+
961
+ let change2 = ChangeFileParams {
962
+ path : path. clone ( ) ,
963
+ version : 3 ,
964
+ changes : vec ! [ ChangeParams {
965
+ text: "" . to_string( ) ,
966
+ range: Some ( TextRange :: new( 0 . into( ) , 1 . into( ) ) ) ,
967
+ } ] ,
968
+ } ;
969
+
970
+ let changes2 = d. apply_file_change ( & change2) ;
971
+
972
+ assert_eq ! ( changes2. len( ) , 1 ) ;
973
+
974
+ assert_document_integrity ( & d) ;
975
+ }
976
+
934
977
#[ test]
935
978
fn apply_changes_at_end_of_statement ( ) {
936
979
let path = PgLTPath :: new ( "test.sql" ) ;
0 commit comments