@@ -151,6 +151,8 @@ impl Document {
151151 let mut start = change_range. start ( ) ;
152152 let mut end = change_range. end ( ) . min ( content_size) ;
153153
154+ let is_trim = change_range. start ( ) >= content_size;
155+
154156 let mut affected_indices = Vec :: new ( ) ;
155157 let mut prev_index = None ;
156158 let mut next_index = None ;
@@ -168,23 +170,20 @@ impl Document {
168170 }
169171 }
170172
171- let start_incl = prev_index
173+ let first_affected_stmt_start = prev_index
172174 . map ( |i| self . positions [ i] . 1 . start ( ) )
173175 . unwrap_or ( start) ;
174- let end_incl = next_index
176+
177+ let mut last_affected_stmt_end = next_index
175178 . map ( |i| self . positions [ i] . 1 . end ( ) )
176179 . unwrap_or_else ( || end) ;
177180
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)
188187 } ;
189188
190189 Affected {
@@ -196,8 +195,10 @@ impl Document {
196195 prev_index,
197196 next_index,
198197 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) ,
201202 ) ,
202203 }
203204 }
@@ -232,6 +233,7 @@ impl Document {
232233 let mut changed: Vec < StatementChange > = Vec :: with_capacity ( self . positions . len ( ) ) ;
233234
234235 let change_range = change. range . unwrap ( ) ;
236+ let previous_content = self . content . clone ( ) ;
235237 let new_content = change. apply_to_text ( & self . content ) ;
236238
237239 // we first need to determine the affected range and all affected statements, as well as
@@ -272,7 +274,7 @@ impl Document {
272274 let new_range = new_ranges[ 0 ] . add ( affected_range. start ( ) ) ;
273275 let ( old_id, old_range) = self . positions [ affected_idx] ;
274276
275- // move all statements after the afffected range
277+ // move all statements after the affected range
276278 self . move_ranges ( old_range. end ( ) , change. diff_size ( ) , change. is_addition ( ) ) ;
277279
278280 let new_id = self . id_generator . next ( ) ;
@@ -283,7 +285,7 @@ impl Document {
283285 id : old_id,
284286 path : self . path . clone ( ) ,
285287 } ,
286- old_stmt_text : self . content [ old_range] . to_string ( ) ,
288+ old_stmt_text : previous_content [ old_range] . to_string ( ) ,
287289
288290 new_stmt : Statement {
289291 id : new_id,
@@ -1325,4 +1327,139 @@ mod tests {
13251327
13261328 assert_document_integrity ( & d) ;
13271329 }
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+ }
13281465}
0 commit comments