@@ -151,6 +151,8 @@ impl Document {
151
151
let mut start = change_range. start ( ) ;
152
152
let mut end = change_range. end ( ) . min ( content_size) ;
153
153
154
+ let is_trim = change_range. start ( ) >= content_size;
155
+
154
156
let mut affected_indices = Vec :: new ( ) ;
155
157
let mut prev_index = None ;
156
158
let mut next_index = None ;
@@ -168,23 +170,20 @@ impl Document {
168
170
}
169
171
}
170
172
171
- let start_incl = prev_index
173
+ let first_affected_stmt_start = prev_index
172
174
. map ( |i| self . positions [ i] . 1 . start ( ) )
173
175
. unwrap_or ( start) ;
174
- let end_incl = next_index
176
+
177
+ let mut last_affected_stmt_end = next_index
175
178
. map ( |i| self . positions [ i] . 1 . end ( ) )
176
179
. unwrap_or_else ( || end) ;
177
180
178
- let end_incl = if is_addition {
179
- end_incl. add ( diff_size)
180
- } else {
181
- end_incl. sub ( diff_size)
182
- } ;
183
-
184
- let end = if is_addition {
185
- end. add ( diff_size)
186
- } else {
187
- end. sub ( diff_size)
181
+ if is_addition {
182
+ end = end. add ( diff_size) ;
183
+ last_affected_stmt_end = last_affected_stmt_end. add ( diff_size) ;
184
+ } else if !is_trim {
185
+ end = end. sub ( diff_size) ;
186
+ last_affected_stmt_end = last_affected_stmt_end. sub ( diff_size)
188
187
} ;
189
188
190
189
Affected {
@@ -196,8 +195,10 @@ impl Document {
196
195
prev_index,
197
196
next_index,
198
197
full_affected_range : TextRange :: new (
199
- start_incl,
200
- end_incl. min ( content_size) . max ( start_incl) ,
198
+ first_affected_stmt_start,
199
+ last_affected_stmt_end
200
+ . min ( content_size)
201
+ . max ( first_affected_stmt_start) ,
201
202
) ,
202
203
}
203
204
}
@@ -232,6 +233,7 @@ impl Document {
232
233
let mut changed: Vec < StatementChange > = Vec :: with_capacity ( self . positions . len ( ) ) ;
233
234
234
235
let change_range = change. range . unwrap ( ) ;
236
+ let previous_content = self . content . clone ( ) ;
235
237
let new_content = change. apply_to_text ( & self . content ) ;
236
238
237
239
// we first need to determine the affected range and all affected statements, as well as
@@ -272,7 +274,7 @@ impl Document {
272
274
let new_range = new_ranges[ 0 ] . add ( affected_range. start ( ) ) ;
273
275
let ( old_id, old_range) = self . positions [ affected_idx] ;
274
276
275
- // move all statements after the afffected range
277
+ // move all statements after the affected range
276
278
self . move_ranges ( old_range. end ( ) , change. diff_size ( ) , change. is_addition ( ) ) ;
277
279
278
280
let new_id = self . id_generator . next ( ) ;
@@ -283,7 +285,7 @@ impl Document {
283
285
id : old_id,
284
286
path : self . path . clone ( ) ,
285
287
} ,
286
- old_stmt_text : self . content [ old_range] . to_string ( ) ,
288
+ old_stmt_text : previous_content [ old_range] . to_string ( ) ,
287
289
288
290
new_stmt : Statement {
289
291
id : new_id,
@@ -1325,4 +1327,139 @@ mod tests {
1325
1327
1326
1328
assert_document_integrity ( & d) ;
1327
1329
}
1330
+
1331
+ #[ test]
1332
+ fn remove_trailing_whitespace ( ) {
1333
+ let path = PgTPath :: new ( "test.sql" ) ;
1334
+
1335
+ let mut doc = Document :: new ( path. clone ( ) , "select * from " . to_string ( ) , 0 ) ;
1336
+
1337
+ let change = ChangeFileParams {
1338
+ path : path. clone ( ) ,
1339
+ version : 1 ,
1340
+ changes : vec ! [ ChangeParams {
1341
+ text: "" . to_string( ) ,
1342
+ range: Some ( TextRange :: new( 13 . into( ) , 14 . into( ) ) ) ,
1343
+ } ] ,
1344
+ } ;
1345
+
1346
+ let changed = doc. apply_file_change ( & change) ;
1347
+
1348
+ assert_eq ! ( doc. content, "select * from" ) ;
1349
+
1350
+ assert_eq ! ( changed. len( ) , 1 ) ;
1351
+
1352
+ match & changed[ 0 ] {
1353
+ StatementChange :: Modified ( stmt) => {
1354
+ let ModifiedStatement {
1355
+ change_range,
1356
+ change_text,
1357
+ new_stmt_text,
1358
+ old_stmt_text,
1359
+ ..
1360
+ } = stmt;
1361
+
1362
+ assert_eq ! ( change_range, & TextRange :: new( 13 . into( ) , 14 . into( ) ) ) ;
1363
+ assert_eq ! ( change_text, "" ) ;
1364
+ assert_eq ! ( new_stmt_text, "select * from" ) ;
1365
+
1366
+ // the whitespace was not considered
1367
+ // to be a part of the statement
1368
+ assert_eq ! ( old_stmt_text, "select * from" ) ;
1369
+ }
1370
+
1371
+ _ => assert ! ( false , "Did not yield a modified statement." ) ,
1372
+ }
1373
+
1374
+ assert_document_integrity ( & doc) ;
1375
+ }
1376
+
1377
+ #[ test]
1378
+ fn remove_trailing_whitespace_and_last_char ( ) {
1379
+ let path = PgTPath :: new ( "test.sql" ) ;
1380
+
1381
+ let mut doc = Document :: new ( path. clone ( ) , "select * from " . to_string ( ) , 0 ) ;
1382
+
1383
+ let change = ChangeFileParams {
1384
+ path : path. clone ( ) ,
1385
+ version : 1 ,
1386
+ changes : vec ! [ ChangeParams {
1387
+ text: "" . to_string( ) ,
1388
+ range: Some ( TextRange :: new( 12 . into( ) , 14 . into( ) ) ) ,
1389
+ } ] ,
1390
+ } ;
1391
+
1392
+ let changed = doc. apply_file_change ( & change) ;
1393
+
1394
+ assert_eq ! ( doc. content, "select * fro" ) ;
1395
+
1396
+ assert_eq ! ( changed. len( ) , 1 ) ;
1397
+
1398
+ match & changed[ 0 ] {
1399
+ StatementChange :: Modified ( stmt) => {
1400
+ let ModifiedStatement {
1401
+ change_range,
1402
+ change_text,
1403
+ new_stmt_text,
1404
+ old_stmt_text,
1405
+ ..
1406
+ } = stmt;
1407
+
1408
+ assert_eq ! ( change_range, & TextRange :: new( 12 . into( ) , 14 . into( ) ) ) ;
1409
+ assert_eq ! ( change_text, "" ) ;
1410
+ assert_eq ! ( new_stmt_text, "select * fro" ) ;
1411
+
1412
+ // the whitespace was not considered
1413
+ // to be a part of the statement
1414
+ assert_eq ! ( old_stmt_text, "select * from" ) ;
1415
+ }
1416
+
1417
+ _ => assert ! ( false , "Did not yield a modified statement." ) ,
1418
+ }
1419
+
1420
+ assert_document_integrity ( & doc) ;
1421
+ }
1422
+
1423
+ #[ test]
1424
+ fn remove_inbetween_whitespace ( ) {
1425
+ let path = PgTPath :: new ( "test.sql" ) ;
1426
+
1427
+ let mut doc = Document :: new ( path. clone ( ) , "select * from users" . to_string ( ) , 0 ) ;
1428
+
1429
+ let change = ChangeFileParams {
1430
+ path : path. clone ( ) ,
1431
+ version : 1 ,
1432
+ changes : vec ! [ ChangeParams {
1433
+ text: "" . to_string( ) ,
1434
+ range: Some ( TextRange :: new( 9 . into( ) , 11 . into( ) ) ) ,
1435
+ } ] ,
1436
+ } ;
1437
+
1438
+ let changed = doc. apply_file_change ( & change) ;
1439
+
1440
+ assert_eq ! ( doc. content, "select * from users" ) ;
1441
+
1442
+ assert_eq ! ( changed. len( ) , 1 ) ;
1443
+
1444
+ match & changed[ 0 ] {
1445
+ StatementChange :: Modified ( stmt) => {
1446
+ let ModifiedStatement {
1447
+ change_range,
1448
+ change_text,
1449
+ new_stmt_text,
1450
+ old_stmt_text,
1451
+ ..
1452
+ } = stmt;
1453
+
1454
+ assert_eq ! ( change_range, & TextRange :: new( 9 . into( ) , 11 . into( ) ) ) ;
1455
+ assert_eq ! ( change_text, "" ) ;
1456
+ assert_eq ! ( old_stmt_text, "select * from users" ) ;
1457
+ assert_eq ! ( new_stmt_text, "select * from users" ) ;
1458
+ }
1459
+
1460
+ _ => assert ! ( false , "Did not yield a modified statement." ) ,
1461
+ }
1462
+
1463
+ assert_document_integrity ( & doc) ;
1464
+ }
1328
1465
}
0 commit comments