Skip to content

Commit 0c8f379

Browse files
committed
fix: multiple changes at once
1 parent 8abc44d commit 0c8f379

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

crates/pgt_workspace/src/workspace.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub use self::client::{TransportRequest, WorkspaceClient, WorkspaceTransport};
44
use pgt_analyse::RuleCategories;
55
use pgt_configuration::{PartialConfiguration, RuleSelector};
66
use pgt_fs::PgTPath;
7-
use pgt_text_size::TextRange;
7+
use pgt_text_size::{TextRange, TextSize};
88
use serde::{Deserialize, Serialize};
99

1010
use crate::{
@@ -58,6 +58,15 @@ impl ChangeParams {
5858
pub fn overwrite(text: String) -> Self {
5959
Self { range: None, text }
6060
}
61+
62+
pub fn push_back(&self, by: TextSize) -> Self {
63+
Self {
64+
range: self
65+
.range
66+
.map(|r| TextRange::new(r.start() + by, r.end() + by)),
67+
text: self.text.clone(),
68+
}
69+
}
6170
}
6271

6372
#[derive(Debug, serde::Serialize, serde::Deserialize)]

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

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,27 @@ struct Affected {
5858
impl Document {
5959
/// Applies a file change to the document and returns the affected statements
6060
pub fn apply_file_change(&mut self, change: &ChangeFileParams) -> Vec<StatementChange> {
61+
tracing::debug!("apply_file_change: {:?}", change);
6162
// cleanup all diagnostics with every change because we cannot guarantee that they are still valid
6263
// this is because we know their ranges only by finding slices within the content which is
6364
// very much not guaranteed to result in correct ranges
6465
self.diagnostics.clear();
6566

66-
let changes = change
67-
.changes
68-
.iter()
69-
.flat_map(|c| self.apply_change(c))
70-
.collect();
67+
let mut changes = Vec::new();
68+
69+
let mut push_back: TextSize = 0.into();
70+
71+
for change in &change.changes {
72+
let change = if push_back > 0.into() {
73+
&change.push_back(push_back)
74+
} else {
75+
change
76+
};
77+
78+
changes.extend(self.apply_change(change));
79+
80+
push_back += change.diff_size();
81+
}
7182

7283
self.version = change.version;
7384

@@ -1522,6 +1533,38 @@ mod tests {
15221533
assert_document_integrity(&doc);
15231534
}
15241535

1536+
#[test]
1537+
fn multiple_changes_at_once() {
1538+
let path = PgTPath::new("test.sql");
1539+
1540+
let mut doc = Document::new("\n\n\n\nALTER TABLE ONLY \"public\".\"sendout\"\n ADD CONSTRAINT \"sendout_organisation_id_fkey\" FOREIGN
1541+
KEY (\"organisation_id\") REFERENCES \"public\".\"organisation\"(\"id\") ON UPDATE RESTRICT ON DELETE CASCADE;\n".to_string(), 0);
1542+
1543+
let change = ChangeFileParams {
1544+
path: path.clone(),
1545+
version: 1,
1546+
changes: vec![
1547+
ChangeParams {
1548+
range: Some(TextRange::new(31.into(), 38.into())),
1549+
text: "omni_channel_message".to_string(),
1550+
},
1551+
ChangeParams {
1552+
range: Some(TextRange::new(60.into(), 67.into())),
1553+
text: "omni_channel_message".to_string(),
1554+
},
1555+
],
1556+
};
1557+
1558+
let changed = doc.apply_file_change(&change);
1559+
1560+
assert_eq!(doc.content, "\n\n\n\nALTER TABLE ONLY \"public\".\"omni_channel_message\"\n ADD CONSTRAINT \"omni_channel_message_organisation_id_fkey\" FOREIGN
1561+
KEY (\"organisation_id\") REFERENCES \"public\".\"organisation\"(\"id\") ON UPDATE RESTRICT ON DELETE CASCADE;\n");
1562+
1563+
assert_eq!(changed.len(), 2);
1564+
1565+
assert_document_integrity(&doc);
1566+
}
1567+
15251568
#[test]
15261569
fn remove_inbetween_whitespace() {
15271570
let path = PgTPath::new("test.sql");

0 commit comments

Comments
 (0)