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