Skip to content

Commit 7278f90

Browse files
fix: properly trim statement (#313)
1 parent 4a10388 commit 7278f90

File tree

1 file changed

+153
-16
lines changed
  • crates/pgt_workspace/src/workspace/server

1 file changed

+153
-16
lines changed

crates/pgt_workspace/src/workspace/server/change.rs

+153-16
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)