From 6346731105c50df2032e4161e94d0221587218ae Mon Sep 17 00:00:00 2001
From: Julian <juliandomke@outlook.de>
Date: Fri, 4 Apr 2025 18:45:03 +0200
Subject: [PATCH 1/7] fix: properly trim statement

---
 .../src/workspace/server/change.rs            | 170 ++++++++++++++++--
 1 file changed, 157 insertions(+), 13 deletions(-)

diff --git a/crates/pgt_workspace/src/workspace/server/change.rs b/crates/pgt_workspace/src/workspace/server/change.rs
index 226a0ffd..30b87a68 100644
--- a/crates/pgt_workspace/src/workspace/server/change.rs
+++ b/crates/pgt_workspace/src/workspace/server/change.rs
@@ -151,6 +151,8 @@ impl Document {
         let mut start = change_range.start();
         let mut end = change_range.end().min(content_size);
 
+        let is_trim = change_range.start() >= content_size;
+
         let mut affected_indices = Vec::new();
         let mut prev_index = None;
         let mut next_index = None;
@@ -168,23 +170,24 @@ impl Document {
             }
         }
 
-        let start_incl = prev_index
+        let first_affected_stmt_start = prev_index
             .map(|i| self.positions[i].1.start())
             .unwrap_or(start);
-        let end_incl = next_index
+
+        let mut last_affected_stmt_end = next_index
             .map(|i| self.positions[i].1.end())
             .unwrap_or_else(|| end);
 
-        let end_incl = if is_addition {
-            end_incl.add(diff_size)
-        } else {
-            end_incl.sub(diff_size)
+        if is_addition {
+            last_affected_stmt_end = last_affected_stmt_end.add(diff_size)
+        } else if !is_trim {
+            last_affected_stmt_end = last_affected_stmt_end.sub(diff_size)
         };
 
-        let end = if is_addition {
-            end.add(diff_size)
-        } else {
-            end.sub(diff_size)
+        if is_addition {
+            end = end.add(diff_size);
+        } else if !is_trim {
+            end = end.sub(diff_size);
         };
 
         Affected {
@@ -195,7 +198,10 @@ impl Document {
             affected_indices,
             prev_index,
             next_index,
-            full_affected_range: TextRange::new(start_incl, end_incl.min(content_size)),
+            full_affected_range: TextRange::new(
+                first_affected_stmt_start,
+                last_affected_stmt_end.min(content_size),
+            ),
         }
     }
 
@@ -229,6 +235,7 @@ impl Document {
         let mut changed: Vec<StatementChange> = Vec::with_capacity(self.positions.len());
 
         let change_range = change.range.unwrap();
+        let previous_content = self.content.clone();
         let new_content = change.apply_to_text(&self.content);
 
         // we first need to determine the affected range and all affected statements, as well as
@@ -269,7 +276,9 @@ impl Document {
                 let new_range = new_ranges[0].add(affected_range.start());
                 let (old_id, old_range) = self.positions[affected_idx];
 
-                // move all statements after the afffected range
+                println!("{:?}", old_range);
+
+                // move all statements after the affected range
                 self.move_ranges(old_range.end(), change.diff_size(), change.is_addition());
 
                 let new_id = self.id_generator.next();
@@ -280,7 +289,7 @@ impl Document {
                         id: old_id,
                         path: self.path.clone(),
                     },
-                    old_stmt_text: self.content[old_range].to_string(),
+                    old_stmt_text: previous_content[old_range].to_string(),
 
                     new_stmt: Statement {
                         id: new_id,
@@ -1322,4 +1331,139 @@ mod tests {
 
         assert_document_integrity(&d);
     }
+
+    #[test]
+    fn remove_trailing_whitespace() {
+        let path = PgTPath::new("test.sql");
+
+        let mut doc = Document::new(path.clone(), "select * from ".to_string(), 0);
+
+        let change = ChangeFileParams {
+            path: path.clone(),
+            version: 1,
+            changes: vec![ChangeParams {
+                text: "".to_string(),
+                range: Some(TextRange::new(13.into(), 14.into())),
+            }],
+        };
+
+        let changed = doc.apply_file_change(&change);
+
+        assert_eq!(doc.content, "select * from");
+
+        assert_eq!(changed.len(), 1);
+
+        match &changed[0] {
+            StatementChange::Modified(stmt) => {
+                let ModifiedStatement {
+                    change_range,
+                    change_text,
+                    new_stmt_text,
+                    old_stmt_text,
+                    ..
+                } = stmt;
+
+                assert_eq!(change_range, &TextRange::new(13.into(), 14.into()));
+                assert_eq!(change_text, "");
+                assert_eq!(new_stmt_text, "select * from");
+
+                // the whitespace was not considered
+                // to be a part of the statement
+                assert_eq!(old_stmt_text, "select * from");
+            }
+
+            _ => panic!("Did not yield a modified statement."),
+        }
+
+        assert_document_integrity(&doc);
+    }
+
+    #[test]
+    fn remove_trailing_whitespace_and_last_char() {
+        let path = PgTPath::new("test.sql");
+
+        let mut doc = Document::new(path.clone(), "select * from ".to_string(), 0);
+
+        let change = ChangeFileParams {
+            path: path.clone(),
+            version: 1,
+            changes: vec![ChangeParams {
+                text: "".to_string(),
+                range: Some(TextRange::new(12.into(), 14.into())),
+            }],
+        };
+
+        let changed = doc.apply_file_change(&change);
+
+        assert_eq!(doc.content, "select * fro");
+
+        assert_eq!(changed.len(), 1);
+
+        match &changed[0] {
+            StatementChange::Modified(stmt) => {
+                let ModifiedStatement {
+                    change_range,
+                    change_text,
+                    new_stmt_text,
+                    old_stmt_text,
+                    ..
+                } = stmt;
+
+                assert_eq!(change_range, &TextRange::new(12.into(), 14.into()));
+                assert_eq!(change_text, "");
+                assert_eq!(new_stmt_text, "select * fro");
+
+                // the whitespace was not considered
+                // to be a part of the statement
+                assert_eq!(old_stmt_text, "select * from");
+            }
+
+            _ => panic!("Did not yield a modified statement."),
+        }
+
+        assert_document_integrity(&doc);
+    }
+
+    #[test]
+    fn remove_inbetween_whitespace() {
+        let path = PgTPath::new("test.sql");
+
+        let mut doc = Document::new(path.clone(), "select *   from users".to_string(), 0);
+
+        let change = ChangeFileParams {
+            path: path.clone(),
+            version: 1,
+            changes: vec![ChangeParams {
+                text: "".to_string(),
+                range: Some(TextRange::new(9.into(), 11.into())),
+            }],
+        };
+
+        let changed = doc.apply_file_change(&change);
+
+        assert_eq!(doc.content, "select * from users");
+
+        assert_eq!(changed.len(), 1);
+
+        match &changed[0] {
+            StatementChange::Modified(stmt) => {
+                let ModifiedStatement {
+                    change_range,
+                    change_text,
+                    new_stmt_text,
+                    old_stmt_text,
+                    ..
+                } = stmt;
+
+                assert_eq!(change_range, &TextRange::new(9.into(), 11.into()));
+                assert_eq!(change_text, "");
+                assert_eq!(old_stmt_text, "select *   from users");
+                assert_eq!(new_stmt_text, "select * from users");
+            }
+
+            _ => panic!("Did not yield a modified statement."),
+        }
+
+        assert_document_integrity(&doc);
+    }
 }

From db2a560b1cc63fa5557f2c730ffea5311f565e2c Mon Sep 17 00:00:00 2001
From: Julian Domke <68325451+juleswritescode@users.noreply.github.com>
Date: Fri, 4 Apr 2025 18:48:09 +0200
Subject: [PATCH 2/7] hell no

---
 crates/pgt_workspace/src/workspace/server/change.rs | 2 --
 1 file changed, 2 deletions(-)

diff --git a/crates/pgt_workspace/src/workspace/server/change.rs b/crates/pgt_workspace/src/workspace/server/change.rs
index 30b87a68..2949b56c 100644
--- a/crates/pgt_workspace/src/workspace/server/change.rs
+++ b/crates/pgt_workspace/src/workspace/server/change.rs
@@ -276,8 +276,6 @@ impl Document {
                 let new_range = new_ranges[0].add(affected_range.start());
                 let (old_id, old_range) = self.positions[affected_idx];
 
-                println!("{:?}", old_range);
-
                 // move all statements after the affected range
                 self.move_ranges(old_range.end(), change.diff_size(), change.is_addition());
 

From 01a6493e8f584f166cdda175f7f790b23086c7df Mon Sep 17 00:00:00 2001
From: Julian <juliandomke@outlook.de>
Date: Fri, 4 Apr 2025 18:49:24 +0200
Subject: [PATCH 3/7] be like the cool kids

---
 crates/pgt_workspace/src/workspace/server/change.rs | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/crates/pgt_workspace/src/workspace/server/change.rs b/crates/pgt_workspace/src/workspace/server/change.rs
index 30b87a68..b0c4a6b9 100644
--- a/crates/pgt_workspace/src/workspace/server/change.rs
+++ b/crates/pgt_workspace/src/workspace/server/change.rs
@@ -180,16 +180,13 @@ impl Document {
 
         if is_addition {
             last_affected_stmt_end = last_affected_stmt_end.add(diff_size)
-        } else if !is_trim {
-            last_affected_stmt_end = last_affected_stmt_end.sub(diff_size)
-        };
-
-        if is_addition {
             end = end.add(diff_size);
         } else if !is_trim {
             end = end.sub(diff_size);
+            last_affected_stmt_end = last_affected_stmt_end.sub(diff_size)
         };
 
+
         Affected {
             affected_range: {
                 let end = end.min(content_size);

From 65fcd19ab8ef7121e76d42372b2a49a2429ea057 Mon Sep 17 00:00:00 2001
From: Julian <juliandomke@outlook.de>
Date: Fri, 4 Apr 2025 18:49:49 +0200
Subject: [PATCH 4/7] i panicked

---
 crates/pgt_workspace/src/workspace/server/change.rs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/crates/pgt_workspace/src/workspace/server/change.rs b/crates/pgt_workspace/src/workspace/server/change.rs
index ec25be3b..0be4db9e 100644
--- a/crates/pgt_workspace/src/workspace/server/change.rs
+++ b/crates/pgt_workspace/src/workspace/server/change.rs
@@ -179,14 +179,13 @@ impl Document {
             .unwrap_or_else(|| end);
 
         if is_addition {
-            last_affected_stmt_end = last_affected_stmt_end.add(diff_size)
             end = end.add(diff_size);
+            last_affected_stmt_end = last_affected_stmt_end.add(diff_size);
         } else if !is_trim {
             end = end.sub(diff_size);
             last_affected_stmt_end = last_affected_stmt_end.sub(diff_size)
         };
 
-
         Affected {
             affected_range: {
                 let end = end.min(content_size);

From 0889ecb774af32bbb8e04dea24d5f1de02ee001e Mon Sep 17 00:00:00 2001
From: Julian Domke <68325451+juleswritescode@users.noreply.github.com>
Date: Sun, 6 Apr 2025 15:37:35 +0200
Subject: [PATCH 5/7] Update
 crates/pgt_workspace/src/workspace/server/change.rs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Philipp Steinrötter <philipp@steinroetter.com>
---
 crates/pgt_workspace/src/workspace/server/change.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crates/pgt_workspace/src/workspace/server/change.rs b/crates/pgt_workspace/src/workspace/server/change.rs
index 0be4db9e..49d5542b 100644
--- a/crates/pgt_workspace/src/workspace/server/change.rs
+++ b/crates/pgt_workspace/src/workspace/server/change.rs
@@ -1455,7 +1455,7 @@ mod tests {
                 assert_eq!(new_stmt_text, "select * from users");
             }
 
-            _ => panic!("Did not yield a modified statement."),
+            _ => assert!(false, "Did not yield a modified statement."),
         }
 
         assert_document_integrity(&doc);

From fab53e49b571ead7d083ac41a545ff270a12a5f5 Mon Sep 17 00:00:00 2001
From: Julian Domke <68325451+juleswritescode@users.noreply.github.com>
Date: Sun, 6 Apr 2025 15:37:44 +0200
Subject: [PATCH 6/7] Update
 crates/pgt_workspace/src/workspace/server/change.rs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Philipp Steinrötter <philipp@steinroetter.com>
---
 crates/pgt_workspace/src/workspace/server/change.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crates/pgt_workspace/src/workspace/server/change.rs b/crates/pgt_workspace/src/workspace/server/change.rs
index 49d5542b..7e491e45 100644
--- a/crates/pgt_workspace/src/workspace/server/change.rs
+++ b/crates/pgt_workspace/src/workspace/server/change.rs
@@ -1412,7 +1412,7 @@ mod tests {
                 assert_eq!(old_stmt_text, "select * from");
             }
 
-            _ => panic!("Did not yield a modified statement."),
+            _ => assert!(false, "Did not yield a modified statement."),
         }
 
         assert_document_integrity(&doc);

From 85dbbcc78f60144dd847dc37b31ab6c7be7dac3d Mon Sep 17 00:00:00 2001
From: Julian Domke <68325451+juleswritescode@users.noreply.github.com>
Date: Sun, 6 Apr 2025 15:37:50 +0200
Subject: [PATCH 7/7] Update
 crates/pgt_workspace/src/workspace/server/change.rs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Philipp Steinrötter <philipp@steinroetter.com>
---
 crates/pgt_workspace/src/workspace/server/change.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crates/pgt_workspace/src/workspace/server/change.rs b/crates/pgt_workspace/src/workspace/server/change.rs
index 7e491e45..e395b282 100644
--- a/crates/pgt_workspace/src/workspace/server/change.rs
+++ b/crates/pgt_workspace/src/workspace/server/change.rs
@@ -1366,7 +1366,7 @@ mod tests {
                 assert_eq!(old_stmt_text, "select * from");
             }
 
-            _ => panic!("Did not yield a modified statement."),
+            _ => assert!(false, "Did not yield a modified statement."),
         }
 
         assert_document_integrity(&doc);