Skip to content

Commit 884034b

Browse files
authored
fix(ui): handle deletion preview end_col safely (#60)
* fix(ui): handle deletion preview end_col safely Ensure that the deletion preview's end_col does not exceed the length of the existing line, preventing potential errors when highlighting deletions in the buffer. This improves robustness when displaying deletion previews. * fix(nes): handle insertions at end of buffer Ensure that edits and preview insertions beyond the buffer's end are handled gracefully. Adjusts logic to walk to the last line if the edit range exceeds buffer length, and fixes preview rendering for insertions at the buffer's end. * chore: fixup * test(ui-preview): handle end_col safely Add a new test to verify that suggestion previews are preserved even when deletions occur before the response is displayed. Includes corresponding screenshots for visual verification. * fix(ui): handle insertions past buffer end in preview Update preview logic to correctly handle cases where insertion line is past the buffer end. Adjust line calculation to avoid out-of-bounds errors and ensure preview displays as expected. Add test case and screenshot for insertion beyond buffer end. * refactor(tests): update ui_preview deletion test logic Simplifies the "deletions before response" test in ui_preview by removing redundant screenshot and state checks. Updates variable names for clarity and applies text edits directly. Removes obsolete screenshot file.
1 parent a80e0c1 commit 884034b

7 files changed

+297
-1
lines changed

lua/copilot-lsp/nes/init.lua

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,24 @@ function M.walk_cursor_start_edit(bufnr)
5252
return false
5353
end
5454

55+
local total_lines = vim.api.nvim_buf_line_count(bufnr)
5556
local cursor_row, _ = unpack(vim.api.nvim_win_get_cursor(0))
57+
if state.range.start.line >= total_lines then
58+
-- If the start line is beyond the end of the buffer then we can't walk there
59+
-- if we are at the end of the buffer, we've walked as we can
60+
if cursor_row == total_lines then
61+
return false
62+
end
63+
-- if not, walk to the end of the buffer instead
64+
vim.lsp.util.show_document({
65+
uri = state.textDocument.uri,
66+
range = {
67+
start = { line = total_lines - 1, character = 0 },
68+
["end"] = { line = total_lines - 1, character = 0 },
69+
},
70+
}, "utf-16", { focus = true })
71+
return true
72+
end
5673
if cursor_row - 1 ~= state.range.start.line then
5774
vim.b[bufnr].nes_jump = true
5875
-- Since we are async, we check to see if the buffer has changed

lua/copilot-lsp/nes/ui.lua

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ function M._calculate_preview(bufnr, edit)
8282
end
8383

8484
if is_insertion and num_new_lines > 1 then
85+
if num_old_lines == 0 then
86+
return {
87+
lines_insertion = {
88+
text = text,
89+
line = start_line,
90+
},
91+
}
92+
end
93+
8594
if start_char == #old_lines[1] and new_lines[1] == "" then
8695
-- insert lines after the start line
8796
return {
@@ -133,10 +142,12 @@ end
133142
function M._display_preview(bufnr, ns_id, preview)
134143
if preview.deletion then
135144
local range = preview.deletion.range
145+
local existing_line = vim.api.nvim_buf_get_lines(bufnr, range["end"].line, range["end"].line + 1, false)[1]
146+
or ""
136147
vim.api.nvim_buf_set_extmark(bufnr, ns_id, range.start.line, range.start.character, {
137148
hl_group = "CopilotLspNesDelete",
138149
end_row = range["end"].line,
139-
end_col = range["end"].character,
150+
end_col = math.min(range["end"].character, #existing_line),
140151
})
141152
end
142153

@@ -154,9 +165,14 @@ function M._display_preview(bufnr, ns_id, preview)
154165
if lines_insertion then
155166
local virt_lines =
156167
require("copilot-lsp.util").hl_text_to_virt_lines(lines_insertion.text, vim.bo[bufnr].filetype)
168+
local total_lines = vim.api.nvim_buf_line_count(bufnr)
169+
if lines_insertion.line >= total_lines then
170+
lines_insertion.line = math.max(total_lines - 1, 0)
171+
end
157172
vim.api.nvim_buf_set_extmark(bufnr, ns_id, lines_insertion.line, 0, {
158173
virt_lines = virt_lines,
159174
virt_lines_above = lines_insertion.above,
175+
strict = false,
160176
})
161177
end
162178
end

tests/nes/test_ui_preview.lua

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,29 @@ local cases = {
221221
},
222222
final = "hijklmn",
223223
},
224+
["insertion only passed buffer end"] = {
225+
content = "function greetName(name: string) : string {",
226+
edit = {
227+
range = {
228+
start = {
229+
line = 2,
230+
character = 0,
231+
},
232+
["end"] = {
233+
line = 2,
234+
character = 0,
235+
},
236+
},
237+
newText = "\treturn `Hello, ${name}!`;\n}\n",
238+
},
239+
preview = {
240+
lines_insertion = {
241+
line = 2,
242+
text = "\treturn `Hello, ${name}!`;\n}\n",
243+
},
244+
},
245+
final = "function greetName(name: string) : string {\n\treturn `Hello, ${name}!`;\n}\n",
246+
},
224247
}
225248

226249
local function set_content(content)
@@ -354,4 +377,40 @@ T["ui_preview"]["suggestion_preserves_on_movement_towards"] = function()
354377
ref(child.get_screenshot())
355378
end
356379

380+
T["ui_preview"]["deletions before response"] = function()
381+
set_content("loooooooooooooooong")
382+
ref(child.get_screenshot())
383+
384+
-- Position cursor at end of line 0
385+
child.cmd("normal! gg$")
386+
387+
-- Create a suggestion at line 0
388+
local edit = {
389+
range = {
390+
start = { line = 0, character = 0 },
391+
["end"] = { line = 0, character = 19 },
392+
},
393+
newText = "long",
394+
}
395+
396+
child.cmd("normal! xxxxxxxxxxxxx") -- Delete text
397+
398+
-- Display suggestion
399+
child.g.inline_edit = edit
400+
child.lua_func(function()
401+
local ns_id = vim.api.nvim_create_namespace("nes_test")
402+
local edits = { vim.g.inline_edit }
403+
require("copilot-lsp.nes.ui")._display_next_suggestion(0, ns_id, edits)
404+
end)
405+
ref(child.get_screenshot())
406+
407+
child.lua_func(function()
408+
local bufnr = vim.api.nvim_get_current_buf()
409+
vim.lsp.util.apply_text_edits({ vim.g.inline_edit }, bufnr, "utf-16")
410+
end)
411+
412+
local final = get_content()
413+
eq(final, edit.newText)
414+
end
415+
357416
return T
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--|---------|---------|---------|---------|---------|---------|---------|---------|
2+
01|loooooooooooooooong
3+
02|~
4+
03|~
5+
04|~
6+
05|~
7+
06|~
8+
07|~
9+
08|~
10+
09|~
11+
10|~
12+
11|~
13+
12|~
14+
13|~
15+
14|~
16+
15|~
17+
16|~
18+
17|~
19+
18|~
20+
19|~
21+
20|~
22+
21|~
23+
22|~
24+
23|[No Name] [+] 1,1 All
25+
24|
26+
27+
--|---------|---------|---------|---------|---------|---------|---------|---------|
28+
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000
29+
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111
30+
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111
31+
04|11111111111111111111111111111111111111111111111111111111111111111111111111111111
32+
05|11111111111111111111111111111111111111111111111111111111111111111111111111111111
33+
06|11111111111111111111111111111111111111111111111111111111111111111111111111111111
34+
07|11111111111111111111111111111111111111111111111111111111111111111111111111111111
35+
08|11111111111111111111111111111111111111111111111111111111111111111111111111111111
36+
09|11111111111111111111111111111111111111111111111111111111111111111111111111111111
37+
10|11111111111111111111111111111111111111111111111111111111111111111111111111111111
38+
11|11111111111111111111111111111111111111111111111111111111111111111111111111111111
39+
12|11111111111111111111111111111111111111111111111111111111111111111111111111111111
40+
13|11111111111111111111111111111111111111111111111111111111111111111111111111111111
41+
14|11111111111111111111111111111111111111111111111111111111111111111111111111111111
42+
15|11111111111111111111111111111111111111111111111111111111111111111111111111111111
43+
16|11111111111111111111111111111111111111111111111111111111111111111111111111111111
44+
17|11111111111111111111111111111111111111111111111111111111111111111111111111111111
45+
18|11111111111111111111111111111111111111111111111111111111111111111111111111111111
46+
19|11111111111111111111111111111111111111111111111111111111111111111111111111111111
47+
20|11111111111111111111111111111111111111111111111111111111111111111111111111111111
48+
21|11111111111111111111111111111111111111111111111111111111111111111111111111111111
49+
22|11111111111111111111111111111111111111111111111111111111111111111111111111111111
50+
23|22222222222222222222222222222222222222222222222222222222222222222222222222222222
51+
24|33333333333333333333333333333333333333333333333333333333333333333333333333333333
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--|---------|---------|---------|---------|---------|---------|---------|---------|
2+
01|looooo
3+
02|long
4+
03|~
5+
04|~
6+
05|~
7+
06|~
8+
07|~
9+
08|~
10+
09|~
11+
10|~
12+
11|~
13+
12|~
14+
13|~
15+
14|~
16+
15|~
17+
16|~
18+
17|~
19+
18|~
20+
19|~
21+
20|~
22+
21|~
23+
22|~
24+
23|[No Name] [+] 1,6 All
25+
24|
26+
27+
--|---------|---------|---------|---------|---------|---------|---------|---------|
28+
01|00000011111111111111111111111111111111111111111111111111111111111111111111111111
29+
02|22221111111111111111111111111111111111111111111111111111111111111111111111111111
30+
03|33333333333333333333333333333333333333333333333333333333333333333333333333333333
31+
04|33333333333333333333333333333333333333333333333333333333333333333333333333333333
32+
05|33333333333333333333333333333333333333333333333333333333333333333333333333333333
33+
06|33333333333333333333333333333333333333333333333333333333333333333333333333333333
34+
07|33333333333333333333333333333333333333333333333333333333333333333333333333333333
35+
08|33333333333333333333333333333333333333333333333333333333333333333333333333333333
36+
09|33333333333333333333333333333333333333333333333333333333333333333333333333333333
37+
10|33333333333333333333333333333333333333333333333333333333333333333333333333333333
38+
11|33333333333333333333333333333333333333333333333333333333333333333333333333333333
39+
12|33333333333333333333333333333333333333333333333333333333333333333333333333333333
40+
13|33333333333333333333333333333333333333333333333333333333333333333333333333333333
41+
14|33333333333333333333333333333333333333333333333333333333333333333333333333333333
42+
15|33333333333333333333333333333333333333333333333333333333333333333333333333333333
43+
16|33333333333333333333333333333333333333333333333333333333333333333333333333333333
44+
17|33333333333333333333333333333333333333333333333333333333333333333333333333333333
45+
18|33333333333333333333333333333333333333333333333333333333333333333333333333333333
46+
19|33333333333333333333333333333333333333333333333333333333333333333333333333333333
47+
20|33333333333333333333333333333333333333333333333333333333333333333333333333333333
48+
21|33333333333333333333333333333333333333333333333333333333333333333333333333333333
49+
22|33333333333333333333333333333333333333333333333333333333333333333333333333333333
50+
23|44444444444444444444444444444444444444444444444444444444444444444444444444444444
51+
24|55555555555555555555555555555555555555555555555555555555555555555555555555555555
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--|---------|---------|---------|---------|---------|---------|---------|---------|
2+
01|function greetName(name: string) : string {
3+
02|~
4+
03|~
5+
04|~
6+
05|~
7+
06|~
8+
07|~
9+
08|~
10+
09|~
11+
10|~
12+
11|~
13+
12|~
14+
13|~
15+
14|~
16+
15|~
17+
16|~
18+
17|~
19+
18|~
20+
19|~
21+
20|~
22+
21|~
23+
22|~
24+
23|[No Name] [+] 1,1 All
25+
24|
26+
27+
--|---------|---------|---------|---------|---------|---------|---------|---------|
28+
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000
29+
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111
30+
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111
31+
04|11111111111111111111111111111111111111111111111111111111111111111111111111111111
32+
05|11111111111111111111111111111111111111111111111111111111111111111111111111111111
33+
06|11111111111111111111111111111111111111111111111111111111111111111111111111111111
34+
07|11111111111111111111111111111111111111111111111111111111111111111111111111111111
35+
08|11111111111111111111111111111111111111111111111111111111111111111111111111111111
36+
09|11111111111111111111111111111111111111111111111111111111111111111111111111111111
37+
10|11111111111111111111111111111111111111111111111111111111111111111111111111111111
38+
11|11111111111111111111111111111111111111111111111111111111111111111111111111111111
39+
12|11111111111111111111111111111111111111111111111111111111111111111111111111111111
40+
13|11111111111111111111111111111111111111111111111111111111111111111111111111111111
41+
14|11111111111111111111111111111111111111111111111111111111111111111111111111111111
42+
15|11111111111111111111111111111111111111111111111111111111111111111111111111111111
43+
16|11111111111111111111111111111111111111111111111111111111111111111111111111111111
44+
17|11111111111111111111111111111111111111111111111111111111111111111111111111111111
45+
18|11111111111111111111111111111111111111111111111111111111111111111111111111111111
46+
19|11111111111111111111111111111111111111111111111111111111111111111111111111111111
47+
20|11111111111111111111111111111111111111111111111111111111111111111111111111111111
48+
21|11111111111111111111111111111111111111111111111111111111111111111111111111111111
49+
22|11111111111111111111111111111111111111111111111111111111111111111111111111111111
50+
23|22222222222222222222222222222222222222222222222222222222222222222222222222222222
51+
24|33333333333333333333333333333333333333333333333333333333333333333333333333333333

0 commit comments

Comments
 (0)