@@ -5,7 +5,11 @@ import { GhostSuggestionsState } from "./GhostSuggestions"
5
5
export class GhostWorkspaceEdit {
6
6
private locked : boolean = false
7
7
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
+ ) {
9
13
const workspaceEdit = new vscode . WorkspaceEdit ( )
10
14
if ( operations . length === 0 ) {
11
15
return // No operations to apply
@@ -16,34 +20,30 @@ export class GhostWorkspaceEdit {
16
20
console . log ( `Could not open document: ${ documentUri . toString ( ) } ` )
17
21
return
18
22
}
19
- const deleteOps = operations . filter ( ( op ) => op . type === "-" )
20
- const insertOps = operations . filter ( ( op ) => op . type === "+" )
21
23
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
25
27
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
34
34
workspaceEdit . delete ( documentUri , range )
35
+ currentLineOffset -- // Each deletion shifts subsequent lines up
36
+ }
37
+ }
35
38
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 )
42
44
const textToInsert = ( op . content || "" ) + "\n"
43
45
workspaceEdit . insert ( documentUri , position , textToInsert )
44
-
45
- lineOffset ++
46
- insPtr ++
46
+ currentLineOffset ++ // Each insertion shifts subsequent lines down
47
47
}
48
48
}
49
49
@@ -67,18 +67,22 @@ export class GhostWorkspaceEdit {
67
67
await vscode . workspace . applyEdit ( workspaceEdit )
68
68
}
69
69
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
+ ) {
71
75
const workspaceEdit = new vscode . WorkspaceEdit ( )
72
76
const document = await vscode . workspace . openTextDocument ( documentUri )
73
77
if ( ! document ) {
74
78
console . log ( `Could not open document: ${ documentUri . toString ( ) } ` )
75
79
return
76
80
}
77
81
78
- let lineOffset = 0
82
+ let currentLineOffset = lineOffset
79
83
for ( const op of operations ) {
80
84
// Calculate the equivalent line in the *original* document.
81
- const originalLine = op . line - lineOffset
85
+ const originalLine = op . line - currentLineOffset
82
86
83
87
// A quick guard against invalid operations.
84
88
if ( originalLine < 0 ) {
@@ -89,15 +93,15 @@ export class GhostWorkspaceEdit {
89
93
const position = new vscode . Position ( originalLine , 0 )
90
94
const textToInsert = "\n"
91
95
workspaceEdit . insert ( documentUri , position , textToInsert )
92
- lineOffset ++
96
+ currentLineOffset ++
93
97
}
94
98
95
99
if ( op . type === "-" ) {
96
100
// Guard against deleting a line that doesn't exist.
97
101
if ( originalLine >= document . lineCount ) {
98
102
continue
99
103
}
100
- lineOffset --
104
+ currentLineOffset --
101
105
}
102
106
}
103
107
0 commit comments