Skip to content

Commit 339529d

Browse files
author
Chris Hasson
committed
fix(ghost): process deletes before inserts when applying edits
We need to compute the Inserts and Deletes from the all operations before each group. Now we pass in `initialLineOffset` to account for previously applied group line offsets
1 parent 8bb66fc commit 339529d

File tree

1 file changed

+32
-28
lines changed

1 file changed

+32
-28
lines changed

src/services/ghost/GhostWorkspaceEdit.ts

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import { GhostSuggestionsState } from "./GhostSuggestions"
55
export class GhostWorkspaceEdit {
66
private locked: boolean = false
77

8-
private async applyOperations(documentUri: vscode.Uri, operations: GhostSuggestionEditOperation[]) {
8+
private async applyOperations(
9+
documentUri: vscode.Uri,
10+
operations: GhostSuggestionEditOperation[],
11+
initialLineOffset: number = 0,
12+
) {
913
const workspaceEdit = new vscode.WorkspaceEdit()
1014
if (operations.length === 0) {
1115
return // No operations to apply
@@ -16,34 +20,30 @@ export class GhostWorkspaceEdit {
1620
console.log(`Could not open document: ${documentUri.toString()}`)
1721
return
1822
}
19-
const deleteOps = operations.filter((op) => op.type === "-")
20-
const insertOps = operations.filter((op) => op.type === "+")
2123

22-
let delPtr = 0
23-
let insPtr = 0
24-
let lineOffset = 0
24+
// Process all deletes first, then all inserts
25+
const deleteOps = operations.filter((op) => op.type === "-").sort((a, b) => b.line - a.line) // Sort deletes in reverse order
26+
const insertOps = operations.filter((op) => op.type === "+").sort((a, b) => a.line - b.line) // Sort inserts in forward order
2527

26-
while (delPtr < deleteOps.length || insPtr < insertOps.length) {
27-
const nextDeleteOriginalLine = deleteOps[delPtr]?.line ?? Infinity
28-
const nextInsertOriginalLine = (insertOps[insPtr]?.line ?? Infinity) - lineOffset
29-
30-
if (nextDeleteOriginalLine <= nextInsertOriginalLine) {
31-
// Process the deletion next
32-
const op = deleteOps[delPtr]
33-
const range = document.lineAt(op.line).rangeIncludingLineBreak
28+
// Process all deletions first (in reverse line order to avoid line number shifts)
29+
let currentLineOffset = initialLineOffset
30+
for (const op of deleteOps) {
31+
const adjustedLine = op.line + currentLineOffset
32+
if (adjustedLine >= 0 && adjustedLine < document.lineCount) {
33+
const range = document.lineAt(adjustedLine).rangeIncludingLineBreak
3434
workspaceEdit.delete(documentUri, range)
35+
currentLineOffset-- // Each deletion shifts subsequent lines up
36+
}
37+
}
3538

36-
lineOffset--
37-
delPtr++
38-
} else {
39-
// Process the insertion next
40-
const op = insertOps[insPtr]
41-
const position = new vscode.Position(nextInsertOriginalLine, 0)
39+
// Process all insertions (in forward line order)
40+
for (const op of insertOps) {
41+
const adjustedLine = op.line + currentLineOffset
42+
if (adjustedLine >= 0) {
43+
const position = new vscode.Position(adjustedLine, 0)
4244
const textToInsert = (op.content || "") + "\n"
4345
workspaceEdit.insert(documentUri, position, textToInsert)
44-
45-
lineOffset++
46-
insPtr++
46+
currentLineOffset++ // Each insertion shifts subsequent lines down
4747
}
4848
}
4949

@@ -67,18 +67,22 @@ export class GhostWorkspaceEdit {
6767
await vscode.workspace.applyEdit(workspaceEdit)
6868
}
6969

70-
private async applyOperationsPlaceholders(documentUri: vscode.Uri, operations: GhostSuggestionEditOperation[]) {
70+
private async applyOperationsPlaceholders(
71+
documentUri: vscode.Uri,
72+
operations: GhostSuggestionEditOperation[],
73+
lineOffset: number = 0,
74+
) {
7175
const workspaceEdit = new vscode.WorkspaceEdit()
7276
const document = await vscode.workspace.openTextDocument(documentUri)
7377
if (!document) {
7478
console.log(`Could not open document: ${documentUri.toString()}`)
7579
return
7680
}
7781

78-
let lineOffset = 0
82+
let currentLineOffset = lineOffset
7983
for (const op of operations) {
8084
// Calculate the equivalent line in the *original* document.
81-
const originalLine = op.line - lineOffset
85+
const originalLine = op.line - currentLineOffset
8286

8387
// A quick guard against invalid operations.
8488
if (originalLine < 0) {
@@ -89,15 +93,15 @@ export class GhostWorkspaceEdit {
8993
const position = new vscode.Position(originalLine, 0)
9094
const textToInsert = "\n"
9195
workspaceEdit.insert(documentUri, position, textToInsert)
92-
lineOffset++
96+
currentLineOffset++
9397
}
9498

9599
if (op.type === "-") {
96100
// Guard against deleting a line that doesn't exist.
97101
if (originalLine >= document.lineCount) {
98102
continue
99103
}
100-
lineOffset--
104+
currentLineOffset--
101105
}
102106
}
103107

0 commit comments

Comments
 (0)