Skip to content

Commit 04d3760

Browse files
committed
fix: ensure right buffers are attached/queried with async model
Fixes #536
1 parent a2a4747 commit 04d3760

File tree

8 files changed

+171
-82
lines changed

8 files changed

+171
-82
lines changed

lua/copilot/auth/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ local function check_status(client, callback)
221221
end
222222

223223
---@param callback? fun()
224+
---@return boolean
224225
function M.is_authenticated(callback)
225226
local current_time = vim.loop.now()
226227

lua/copilot/client/init.lua

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,13 @@ local is_disabled = false
1414
---@field config vim.lsp.ClientConfig | nil
1515
---@field startup_error string | nil
1616
---@field initialized boolean
17-
-- Only for informational purposes, use Vim API to check actual status
18-
---@field buffer_statuses table<integer, string>
1917
local M = {
2018
augroup = nil,
2119
id = nil,
2220
capabilities = nil,
2321
config = nil,
2422
startup_error = nil,
2523
initialized = false,
26-
buffer_statuses = {},
2724
}
2825

2926
---@param id integer
@@ -42,8 +39,21 @@ function M.buf_is_attached(bufnr)
4239
end
4340

4441
---@param force? boolean
45-
function M.buf_attach(force)
46-
local bufnr = vim.api.nvim_get_current_buf()
42+
---@param bufnr? integer The buffer number of which will be attached. 0 or nil for current buffer
43+
function M.buf_attach(force, bufnr)
44+
if bufnr then
45+
logger.trace("request to attach buffer #" .. tostring(bufnr))
46+
end
47+
48+
bufnr = bufnr or vim.api.nvim_get_current_buf()
49+
if bufnr == 0 then
50+
bufnr = vim.api.nvim_get_current_buf()
51+
end
52+
53+
if not vim.api.nvim_buf_is_valid(bufnr) then
54+
logger.trace("buffer is invalid")
55+
return
56+
end
4757

4858
if M.buf_is_attached(bufnr) then
4959
logger.trace("buffer already attached")
@@ -61,11 +71,11 @@ function M.buf_attach(force)
6171
return
6272
end
6373

64-
local should_attach, reason = util.should_attach()
74+
local should_attach, reason = util.should_attach(bufnr)
6575

6676
if not (force or should_attach) then
6777
logger.debug("not attaching to buffer based should_attach criteria: " .. reason)
68-
M.buffer_statuses[bufnr] = "not attached based on " .. reason
78+
util.set_buffer_attach_status(bufnr, ATTACH_STATUS_NOT_ATTACHED_PREFIX .. reason)
6979
return
7080
end
7181

@@ -88,18 +98,18 @@ function M.buf_attach(force)
8898
vim.lsp.buf_attach_client(bufnr, M.id)
8999
if force then
90100
logger.debug("force attached to buffer")
91-
M.buffer_statuses[bufnr] = "force attached"
101+
util.set_buffer_attach_status(bufnr, ATTACH_STATUS_FORCE_ATTACHED)
92102
else
93103
logger.trace("buffer attached")
94-
M.buffer_statuses[bufnr] = "attached"
104+
util.set_buffer_attach_status(bufnr, ATTACH_STATUS_ATTACHED)
95105
end
96106
end
97107

98108
function M.buf_detach()
99109
if M.buf_is_attached(0) then
100110
vim.lsp.buf_detach_client(0, M.id)
101-
logger.trace("buffer detached")
102-
M.buffer_statuses[vim.api.nvim_get_current_buf()] = "manually detached"
111+
logger.trace("buffer manuall detached")
112+
util.set_buffer_attach_status(vim.api.nvim_get_current_buf(), ATTACH_STATUS_MANUALLY_DETACHED)
103113
end
104114
end
105115

@@ -176,19 +186,23 @@ function M.setup()
176186

177187
vim.api.nvim_create_autocmd("FileType", {
178188
group = M.augroup,
179-
callback = function()
189+
callback = function(args)
190+
local bufnr = (args and args.buf) or nil
180191
logger.trace("filetype autocmd called")
181192
vim.schedule(function()
182193
-- todo: when we do lazy/late attaching this needs changing
183-
M.buf_attach()
194+
M.buf_attach(false, bufnr)
184195
end)
185196
end,
186197
desc = "[copilot] (suggestion) file type",
187198
})
188199

189200
vim.schedule(M.ensure_client_started)
190-
-- FileType is likely already triggered for shown buffer
191-
vim.schedule(M.buf_attach)
201+
-- FileType is likely already triggered for shown buffer, so we trigger it manually
202+
local bufnr = vim.api.nvim_get_current_buf()
203+
vim.schedule(function()
204+
M.buf_attach(false, bufnr)
205+
end)
192206
end
193207

194208
function M.teardown()

lua/copilot/command.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ function M.version()
2929
end)()
3030
end
3131

32-
---@param opts? { force?: boolean }
32+
---@param opts? { force?: boolean, bufnr?: integer}
3333
function M.attach(opts)
3434
logger.trace("attaching to buffer")
3535
opts = opts or {}
3636

3737
if not opts.force then
38-
local should_attach, no_attach_reason = u.should_attach()
38+
local should_attach, no_attach_reason = u.should_attach(opts.bufnr)
3939

4040
if not should_attach then
4141
logger.notify(no_attach_reason .. "\nto force attach, run ':Copilot! attach'")
@@ -45,7 +45,7 @@ function M.attach(opts)
4545
opts.force = true
4646
end
4747

48-
c.buf_attach(opts.force)
48+
c.buf_attach(opts.force, opts.bufnr)
4949
end
5050

5151
function M.detach()

lua/copilot/status/init.lua

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
local u = require("copilot.util")
12
local logger = require("copilot.logger")
23
---@alias copilot_status_notification_data { status: ''|'Normal'|'InProgress'|'Warning', message: string }
34

@@ -97,12 +98,8 @@ function M.status()
9798
return
9899
end
99100

100-
local buffer_status = c.buffer_statuses[vim.api.nvim_get_current_buf()]
101-
if buffer_status then
102-
add_line("Buffer status: " .. c.buffer_statuses[vim.api.nvim_get_current_buf()])
103-
else
104-
add_line("Buffer status: Attach not yet requested")
105-
end
101+
local buffer_status = u.get_buffer_attach_status(vim.api.nvim_get_current_buf())
102+
add_line("Buffer status: " .. buffer_status)
106103

107104
if string.lower(M.data.status) == "error" then
108105
add_line(M.data.message)

lua/copilot/suggestion/init.lua

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ local function clear_preview()
236236
end
237237

238238
---@param ctx? copilot_suggestion_context
239-
---@return copilot_get_completions_data_completion|nil
239+
---@return copilot_get_completions_data_completion?
240240
local function get_current_suggestion(ctx)
241241
logger.trace("suggestion get current suggestion", ctx)
242242
ctx = ctx or get_ctx()
@@ -454,10 +454,11 @@ local function get_suggestions_cycling(callback, ctx)
454454
end
455455
end
456456

457-
local function schedule(ctx)
457+
---@param bufnr? integer
458+
local function schedule(bufnr)
458459
local function is_authenticated()
459460
return auth.is_authenticated(function()
460-
schedule(ctx)
461+
schedule(bufnr)
461462
end)
462463
end
463464

@@ -467,36 +468,35 @@ local function schedule(ctx)
467468
return
468469
end
469470

470-
logger.trace("suggestion schedule", ctx)
471+
logger.trace("suggestion schedule")
471472

472473
if copilot._copilot_timer then
473-
cancel_inflight_requests(ctx)
474+
cancel_inflight_requests()
474475
stop_timer()
475476
end
476477

477-
update_preview(ctx)
478-
local bufnr = vim.api.nvim_get_current_buf()
478+
update_preview()
479+
bufnr = bufnr or vim.api.nvim_get_current_buf()
479480
copilot._copilot_timer = vim.fn.timer_start(copilot.debounce, function(timer)
480481
logger.trace("suggestion schedule timer", bufnr)
481482
trigger(bufnr, timer)
482483
end)
483484
end
484485

485-
---@param context string
486-
local function request_suggestion(context)
487-
logger.trace("suggestion on " .. context)
488-
schedule()
486+
---@param bufnr? integer
487+
local function request_suggestion(bufnr)
488+
logger.trace("suggestion request")
489+
c.buf_attach(false, bufnr)
490+
schedule(bufnr)
489491
end
490492

491-
---@param context string
492-
local function request_suggestion_when_auto_trigger(context)
493-
c.buf_attach()
494-
493+
---@param bufnr? integer
494+
local function request_suggestion_when_auto_trigger(bufnr)
495495
if not should_auto_trigger() then
496496
return
497497
end
498498

499-
request_suggestion(context)
499+
request_suggestion(bufnr)
500500
end
501501

502502
function M.has_next()
@@ -524,12 +524,11 @@ local function advance(count, ctx)
524524
end
525525

526526
---@param ctx copilot_suggestion_context
527-
---@param caller_context string
528527
---@return boolean
529-
function M.first_request_scheduled(ctx, caller_context)
528+
function M.first_request_scheduled(ctx)
530529
if not ctx.first then
531-
logger.trace("suggestion " .. caller_context .. ", no first request")
532-
request_suggestion(caller_context)
530+
logger.trace("suggestion, no first request")
531+
request_suggestion()
533532
return true
534533
end
535534

@@ -544,7 +543,7 @@ function M.next()
544543
reset_ctx(ctx)
545544
end
546545

547-
if M.first_request_scheduled(ctx, "next") then
546+
if M.first_request_scheduled(ctx) then
548547
return
549548
end
550549

@@ -561,7 +560,7 @@ function M.prev()
561560
reset_ctx(ctx)
562561
end
563562

564-
if M.first_request_scheduled(ctx, "prev") then
563+
if M.first_request_scheduled(ctx) then
565564
return
566565
end
567566

@@ -575,7 +574,7 @@ function M.accept(modifier)
575574
local ctx = get_ctx()
576575
logger.trace("suggestion accept", ctx)
577576

578-
if config.suggestion.trigger_on_accept and M.first_request_scheduled(ctx, "suggestion accept") then
577+
if config.suggestion.trigger_on_accept and M.first_request_scheduled(ctx) then
579578
return
580579
end
581580

@@ -736,33 +735,41 @@ local function on_buf_leave()
736735
end
737736
end
738737

739-
local function on_insert_enter()
740-
request_suggestion_when_auto_trigger("insert enter")
738+
local function on_insert_enter(args)
739+
logger.trace("insert enter")
740+
local bufnr = (args and args.buf) or nil
741+
request_suggestion_when_auto_trigger(bufnr)
741742
end
742743

743-
local function on_buf_enter()
744+
local function on_buf_enter(args)
744745
if vim.fn.mode():match("^[iR]") then
745-
request_suggestion_when_auto_trigger("buf enter")
746+
logger.trace("buf enter")
747+
local bufnr = (args and args.buf) or nil
748+
request_suggestion_when_auto_trigger(bufnr)
746749
end
747750
end
748751

749-
local function on_cursor_moved_i()
752+
local function on_cursor_moved_i(args)
750753
if ignore_next_cursor_moved then
751754
ignore_next_cursor_moved = false
752755
return
753756
end
754757

755758
local ctx = get_ctx()
756759
if copilot._copilot_timer or ctx.params or should_auto_trigger() then
757-
request_suggestion("cursor moved insert")
760+
logger.trace("cursor moved insert")
761+
local bufnr = (args and args.buf) or nil
762+
request_suggestion(bufnr)
758763
end
759764
end
760765

761-
local function on_text_changed_p()
766+
local function on_text_changed_p(args)
762767
local ctx = get_ctx()
763768

764769
if not copilot.hide_during_completion and (copilot._copilot_timer or ctx.params or should_auto_trigger()) then
765-
request_suggestion("text changed pum")
770+
logger.trace("text changed pum")
771+
local bufnr = (args and args.buf) or nil
772+
request_suggestion(bufnr)
766773
end
767774
end
768775

@@ -797,25 +804,33 @@ local function create_autocmds()
797804

798805
vim.api.nvim_create_autocmd("InsertEnter", {
799806
group = copilot.augroup,
800-
callback = on_insert_enter,
807+
callback = function(args)
808+
on_insert_enter(args)
809+
end,
801810
desc = "[copilot] (suggestion) insert enter",
802811
})
803812

804813
vim.api.nvim_create_autocmd("BufEnter", {
805814
group = copilot.augroup,
806-
callback = on_buf_enter,
815+
callback = function(args)
816+
on_buf_enter(args)
817+
end,
807818
desc = "[copilot] (suggestion) buf enter",
808819
})
809820

810821
vim.api.nvim_create_autocmd("CursorMovedI", {
811822
group = copilot.augroup,
812-
callback = on_cursor_moved_i,
823+
callback = function(args)
824+
on_cursor_moved_i(args)
825+
end,
813826
desc = "[copilot] (suggestion) cursor moved insert",
814827
})
815828

816829
vim.api.nvim_create_autocmd("TextChangedP", {
817830
group = copilot.augroup,
818-
callback = on_text_changed_p,
831+
callback = function(args)
832+
on_text_changed_p(args)
833+
end,
819834
desc = "[copilot] (suggestion) text changed pum",
820835
})
821836

@@ -827,7 +842,9 @@ local function create_autocmds()
827842

828843
vim.api.nvim_create_autocmd("BufUnload", {
829844
group = copilot.augroup,
830-
callback = on_buf_unload,
845+
callback = function(args)
846+
on_buf_unload(args)
847+
end,
831848
desc = "[copilot] (suggestion) buf unload",
832849
})
833850

0 commit comments

Comments
 (0)