From e69323a87c2d547fb0d52bc1a31b8f2f2ed04a77 Mon Sep 17 00:00:00 2001 From: Antoine Gaudreau Simard Date: Sun, 30 Mar 2025 18:58:35 -0400 Subject: [PATCH 1/7] refactor!: major rewrite of project structure --- lua/copilot/{api.lua => api/init.lua} | 0 lua/copilot/{auth.lua => auth/init.lua} | 0 lua/copilot/{client.lua => client/init.lua} | 117 ++++------------- lua/copilot/client/utils.lua | 21 +++ lua/copilot/config.lua | 123 ------------------ lua/copilot/config/init.lua | 55 ++++++++ lua/copilot/config/logger.lua | 21 +++ lua/copilot/config/panel.lua | 37 ++++++ lua/copilot/config/root_dir.lua | 10 ++ lua/copilot/config/server.lua | 13 ++ lua/copilot/config/should_attach.lua | 22 ++++ lua/copilot/config/suggestion.lua | 34 +++++ lua/copilot/init.lua | 34 +---- lua/copilot/{logger.lua => logger/init.lua} | 80 ++++++------ .../{lsp_binary.lua => lsp/binary.lua} | 0 lua/copilot/lsp/init.lua | 6 + .../{lsp_nodejs.lua => lsp/nodejs.lua} | 0 lua/copilot/{panel.lua => panel/init.lua} | 4 +- .../{suggestion.lua => suggestion/init.lua} | 4 +- lua/copilot/util.lua | 9 +- .../{workspace.lua => workspace/init.lua} | 0 lua/copilot/workspace/utils.lua | 57 ++++++++ 22 files changed, 352 insertions(+), 295 deletions(-) rename lua/copilot/{api.lua => api/init.lua} (100%) rename lua/copilot/{auth.lua => auth/init.lua} (100%) rename lua/copilot/{client.lua => client/init.lua} (71%) create mode 100644 lua/copilot/client/utils.lua delete mode 100644 lua/copilot/config.lua create mode 100644 lua/copilot/config/init.lua create mode 100644 lua/copilot/config/logger.lua create mode 100644 lua/copilot/config/panel.lua create mode 100644 lua/copilot/config/root_dir.lua create mode 100644 lua/copilot/config/server.lua create mode 100644 lua/copilot/config/should_attach.lua create mode 100644 lua/copilot/config/suggestion.lua rename lua/copilot/{logger.lua => logger/init.lua} (64%) rename lua/copilot/{lsp_binary.lua => lsp/binary.lua} (100%) create mode 100644 lua/copilot/lsp/init.lua rename lua/copilot/{lsp_nodejs.lua => lsp/nodejs.lua} (100%) rename lua/copilot/{panel.lua => panel/init.lua} (99%) rename lua/copilot/{suggestion.lua => suggestion/init.lua} (99%) rename lua/copilot/{workspace.lua => workspace/init.lua} (100%) create mode 100644 lua/copilot/workspace/utils.lua diff --git a/lua/copilot/api.lua b/lua/copilot/api/init.lua similarity index 100% rename from lua/copilot/api.lua rename to lua/copilot/api/init.lua diff --git a/lua/copilot/auth.lua b/lua/copilot/auth/init.lua similarity index 100% rename from lua/copilot/auth.lua rename to lua/copilot/auth/init.lua diff --git a/lua/copilot/client.lua b/lua/copilot/client/init.lua similarity index 71% rename from lua/copilot/client.lua rename to lua/copilot/client/init.lua index 96e80d7e..f271f8f3 100644 --- a/lua/copilot/client.lua +++ b/lua/copilot/client/init.lua @@ -2,8 +2,8 @@ local api = require("copilot.api") local config = require("copilot.config") local util = require("copilot.util") local logger = require("copilot.logger") -local lsp_binary = require("copilot.lsp_binary") -local lsp_nodesj = require("copilot.lsp_nodejs") +local lsp = require("copilot.lsp") +local utils = require("copilot.client.utils") local is_disabled = false @@ -11,22 +11,11 @@ local M = { augroup = "copilot.client", id = nil, --- @class copilot_capabilities:lsp.ClientCapabilities - --- @field copilot table<'openURL', boolean> --- @field workspace table<'workspaceFolders', boolean> capabilities = nil, config = nil, startup_error = nil, initialized = false, - ---@type copilot_should_attach - should_attach = nil, - ---@type string<'nodejs', 'binary'> - ---@class copilot_config_server - server = { - ---@type string<'nodejs', 'binary'> - type = "nodejs", - ---@type string|nil - custom_server_filepath = nil, - }, } ---@param id integer @@ -46,7 +35,7 @@ end ---@param force? boolean function M.buf_attach(force) - if lsp_binary.initialization_failed then + if lsp.binary.initialization_failed then M.startup_error = "initialization of copilot-language-server failed" return end @@ -59,7 +48,7 @@ function M.buf_attach(force) local bufnr = vim.api.nvim_get_current_buf() local bufname = vim.api.nvim_buf_get_name(bufnr) - if not (force or (M.should_attach(bufnr, bufname) and util.should_attach())) then + if not (force or (config.should_attach(bufnr, bufname) and util.should_attach())) then logger.debug("not attaching to buffer based on force and should_attach criteria") return end @@ -70,7 +59,7 @@ function M.buf_attach(force) end -- In case it has changed, we update it - M.config.root_dir = config.get_root_dir() + M.config.root_dir = utils.get_root_dir(config.root_dir) local ok, client_id_or_err = pcall(vim.lsp.start, M.config) if not ok then @@ -161,7 +150,7 @@ local function get_handlers() } -- optional handlers - local logger_conf = config.config.logger + local logger_conf = config.logger if logger_conf.trace_lsp ~= "off" then handlers = vim.tbl_extend("force", handlers, { ["$/logTrace"] = logger.handle_lsp_trace, @@ -184,7 +173,7 @@ local function get_handlers() end local function prepare_client_config(overrides) - if lsp_binary.initialization_failed then + if lsp.binary.initialization_failed then M.startup_error = "initialization of copilot-language-server failed" return end @@ -194,19 +183,19 @@ local function prepare_client_config(overrides) local server_path = nil local cmd = nil - if M.server.custom_server_filepath and vim.fn.filereadable(M.server.custom_server_filepath) then - server_path = M.server.custom_server_filepath + if config.server.custom_server_filepath and vim.fn.filereadable(config.server.custom_server_filepath) then + server_path = config.server.custom_server_filepath end - if M.server.type == "nodejs" then + if config.server.type == "nodejs" then cmd = { - lsp_nodesj.node_command, - server_path or lsp_nodesj.get_server_path(), + lsp.nodejs.node_command, + server_path or lsp.nodejs.get_server_path(), "--stdio", } - elseif M.server.type == "binary" then + elseif config.server.type == "binary" then cmd = { - server_path or lsp_binary.get_server_path(), + server_path or lsp.binary.get_server_path(), "--stdio", } end @@ -223,7 +212,7 @@ local function prepare_client_config(overrides) workspaceFolders = true, } - local root_dir = config.get_root_dir() + local root_dir = utils.get_root_dir(config.root_dir) local workspace_folders = { --- @type workspace_folder { @@ -233,7 +222,7 @@ local function prepare_client_config(overrides) }, } - local config_workspace_folders = config.config.workspace_folders + local config_workspace_folders = config.workspace_folders for _, config_workspace_folder in ipairs(config_workspace_folders) do if config_workspace_folder ~= "" then @@ -249,7 +238,7 @@ local function prepare_client_config(overrides) end local editor_info = util.get_editor_info() - local provider_url = config.config.auth_provider_url + local provider_url = config.auth_provider_url local proxy_uri = vim.g.copilot_proxy local settings = { ---@type copilot_settings @@ -296,7 +285,7 @@ local function prepare_client_config(overrides) logger.trace("workspace configuration", configurations) -- to activate tracing if we want it - local logger_conf = config.config.logger + local logger_conf = config.logger local trace_params = { value = logger_conf.trace_lsp } --[[@as copilot_nofify_set_trace_params]] api.notify_set_trace(client, trace_params) @@ -329,22 +318,16 @@ local function prepare_client_config(overrides) end function M.setup() - M.should_attach = config.config.should_attach - local server_config = config.config.server - local node_command = config.config.copilot_node_command - M.server = vim.tbl_deep_extend("force", M.server, server_config) + local node_command = config.copilot_node_command - if M.server.custom_server_filepath then - M.server.custom_server_filepath = vim.fs.normalize(M.server.custom_server_filepath) + --TODO: merge the two types into an indirection + if config.server.type == "nodejs" then + lsp.nodejs.setup(node_command, config.server.custom_server_filepath) + elseif config.server.type == "binary" then + lsp.binary.setup(config.server.custom_server_filepath) end - if M.server.type == "nodejs" then - lsp_nodesj.setup(node_command, M.server.custom_server_filepath) - elseif M.server.type == "binary" then - lsp_binary.setup(M.server.custom_server_filepath) - end - - M.config = prepare_client_config(config.config.server_opts_overrides) + M.config = prepare_client_config(config.server_opts_overrides) if not M.config then is_disabled = true @@ -378,54 +361,4 @@ function M.teardown() end end -function M.add_workspace_folder(folder_path) - if type(folder_path) ~= "string" then - logger.error("workspace folder path must be a string") - return false - end - - if vim.fn.isdirectory(folder_path) ~= 1 then - logger.error("invalid workspace folder: " .. folder_path) - return false - end - - -- Normalize path - folder_path = vim.fn.fnamemodify(folder_path, ":p") - - --- @type workspace_folder - local workspace_folder = { - uri = vim.uri_from_fname(folder_path), - name = folder_path, - } - - local workspace_folders = config.config.workspace_folders - if not workspace_folders then - workspace_folders = {} - end - - for _, existing_folder in ipairs(workspace_folders) do - if existing_folder == folder_path then - return - end - end - - table.insert(workspace_folders, { folder_path }) - config.set("workspace_folders", workspace_folders) - - local client = M.get() - if client and client.initialized then - api.notify(client, "workspace/didChangeWorkspaceFolders", { - event = { - added = { workspace_folder }, - removed = {}, - }, - }) - logger.notify("added workspace folder: " .. folder_path) - else - logger.notify("workspace folder will be added on next session: " .. folder_path) - end - - return true -end - return M diff --git a/lua/copilot/client/utils.lua b/lua/copilot/client/utils.lua new file mode 100644 index 00000000..757eab9c --- /dev/null +++ b/lua/copilot/client/utils.lua @@ -0,0 +1,21 @@ +local M = {} + +---@param config_root_dir RootDirFuncOrString +function M.get_root_dir(config_root_dir) + local root_dir --[[@as string]] + + if type(config_root_dir) == "function" then + root_dir = config_root_dir() + else + root_dir = config_root_dir + end + + if not root_dir or root_dir == "" then + root_dir = "." + end + + root_dir = vim.fn.fnamemodify(root_dir, ":p:h") + return root_dir +end + +return M diff --git a/lua/copilot/config.lua b/lua/copilot/config.lua deleted file mode 100644 index 212b5fcf..00000000 --- a/lua/copilot/config.lua +++ /dev/null @@ -1,123 +0,0 @@ -local logger = require("copilot.logger") - ----@class copilot_config -local default_config = { - ---@class copilot_config_panel - panel = { - enabled = true, - auto_refresh = false, - ---@type table<'jump_prev'|'jump_next'|'accept'|'refresh'|'open', false|string> - keymap = { - jump_prev = "[[", - jump_next = "]]", - accept = "", - refresh = "gr", - open = "", - }, - layout = { - position = "bottom", - ratio = 0.4, - }, - }, - ---@class copilot_config_suggestion - suggestion = { - enabled = true, - auto_trigger = false, - hide_during_completion = true, - debounce = 15, - ---@type table<'accept'|'accept_word'|'accept_line'|'next'|'prev'|'dismiss', false|string> - keymap = { - accept = "", - accept_word = false, - accept_line = false, - next = "", - prev = "", - dismiss = "", - }, - }, - ---@class copilot_config_logging - logger = { - file = vim.fn.stdpath("log") .. "/copilot-lua.log", - file_log_level = vim.log.levels.OFF, - print_log_level = vim.log.levels.WARN, - ---@type string<'off'|'messages'|'verbose'> - trace_lsp = "off", - trace_lsp_progress = false, - log_lsp_messages = false, - }, - ---@type table - filetypes = {}, - ---@type string|nil - auth_provider_url = nil, - ---@type string[] - workspace_folders = {}, - server_opts_overrides = {}, - ---@type string|nil - copilot_model = nil, - ---@type function|string - root_dir = function() - return vim.fs.dirname(vim.fs.find(".git", { upward = true })[1]) - end, - ---@alias copilot_should_attach fun(bufnr: integer, bufname: string): boolean - ---@type copilot_should_attach - should_attach = function(_, _) - if not vim.bo.buflisted then - logger.debug("not attaching, bugger is not 'buflisted'") - return false - end - - if vim.bo.buftype ~= "" then - logger.debug("not attaching, buffer 'buftype' is " .. vim.bo.buftype) - return false - end - - return true - end, - copilot_node_command = "node", - ---@class copilot_config_server - server = { - ---@type string<'nodejs', 'binary'> - type = "nodejs", - ---@type string|nil - custom_server_filepath = nil, - }, -} - -local mod = { - ---@type copilot_config - config = nil, -} - -function mod.setup(opts) - if mod.config then - logger.warn("config is already set") - return mod.config - end - - mod.config = vim.tbl_deep_extend("force", default_config, opts or {}) - return mod.config -end - -function mod.get_root_dir() - if not mod.config then - error("[Copilot] not initialized") - end - - local config_root_dir = mod.config.root_dir - local root_dir --[[@as string]] - - if type(config_root_dir) == "function" then - root_dir = config_root_dir() - else - root_dir = config_root_dir - end - - if not root_dir or root_dir == "" then - root_dir = "." - end - - root_dir = vim.fn.fnamemodify(root_dir, ":p:h") - return root_dir -end - -return mod diff --git a/lua/copilot/config/init.lua b/lua/copilot/config/init.lua new file mode 100644 index 00000000..dfafdcc7 --- /dev/null +++ b/lua/copilot/config/init.lua @@ -0,0 +1,55 @@ +local logger = require("copilot.logger") + +---@class CopilotConfig +---@field panel PanelConfig +---@field suggestion SuggestionConfig +---@field logger LoggerConfig +---@field server ServerConfig +---@field filetypes table Filetypes to enable Copilot for +---@field auth_provider_url string|nil URL for the authentication provider +---@field workspace_folders string[] Workspace folders to enable Copilot for +---@field server_opts_overrides table Options to override for the server +---@field copilot_model string|nil Model to use for Copilot, LSP server dictates the default +---@field root_dir RootDirFuncOrString Root directory for the project, defaults to the nearest .git directory +---@field should_attach ShouldAttachFunc Function to determine if Copilot should attach to the buffer +---@field copilot_node_command string Path to the Node.js executable, defaults to "node" + +local initialized = false + +---@class CopilotConfig +local M = { + panel = require("copilot.config.panel").default, + suggestion = require("copilot.config.suggestion").default, + logger = require("copilot.config.logger").default, + server = require("copilot.config.server").default, + root_dir = require("copilot.config.root_dir").default, + should_attach = require("copilot.config.should_attach").default, + filetypes = {}, + auth_provider_url = nil, + workspace_folders = {}, + server_opts_overrides = {}, + copilot_model = nil, + copilot_node_command = "node", +} + +function M.merge_with_user_configs(user_configs) + logger.trace("setting up configuration, opts", user_configs) + + if initialized then + logger.warn("config is already set") + return + end + + local merged = vim.tbl_deep_extend("force", M, user_configs or {}) + for k, v in pairs(merged) do + M[k] = v + end + + if M.server.custom_server_filepath then + M.server.custom_server_filepath = vim.fs.normalize(M.server.custom_server_filepath) + end + + initialized = true +end + +return M diff --git a/lua/copilot/config/logger.lua b/lua/copilot/config/logger.lua new file mode 100644 index 00000000..4dff13a4 --- /dev/null +++ b/lua/copilot/config/logger.lua @@ -0,0 +1,21 @@ +---@class LoggerConfig +---@field file string Path to the log file +---@field file_log_level integer Log level for the log file, matches vim.log.levels +---@field print_log_level integer Log level for printing to the console, matches vim.log.levels +---@field trace_lsp string Trace level for LSP messages, current does not seem to do anything +---@field trace_lsp_progress boolean Whether to show LSP progress messages +---@field log_lsp_messages boolean Whether to log LSP messages + +local logger = { + ---@type LoggerConfig + default = { + file = vim.fn.stdpath("log") .. "/copilot-lua.log", + file_log_level = vim.log.levels.OFF, + print_log_level = vim.log.levels.WARN, + trace_lsp = "off", + trace_lsp_progress = false, + log_lsp_messages = false, + }, +} + +return logger diff --git a/lua/copilot/config/panel.lua b/lua/copilot/config/panel.lua new file mode 100644 index 00000000..93a9550b --- /dev/null +++ b/lua/copilot/config/panel.lua @@ -0,0 +1,37 @@ +---@class PanelConfig +---@field enabled boolean Whether to enable the panel +---@field auto_refresh boolean Whether to automatically refresh the panel +---@field keymap PanelKeymapConfig Keymap for the panel +---@field layout config_panel_layout Layout of the panel + +---@class PanelKeymapConfig +---@field jump_prev string|false Keymap for jumping to the previous suggestion +---@field jump_next string|false Keymap for jumping to the next suggestion +---@field accept string|false Keymap for accepting the suggestion +---@field refresh string|false Keymap for refreshing the suggestion +---@field open string|false Keymap for opening the suggestion + +---@class config_panel_layout +---@field position string<'left'|'right'|'top'|'bottom'> Position of the panel +---@field ratio number Ratio of the panel size, between 0 and 1 + +local panel = { + ---@type PanelConfig + default = { + enabled = true, + auto_refresh = false, + keymap = { + jump_prev = "[[", + jump_next = "]]", + accept = "", + refresh = "gr", + open = "", + }, + layout = { + position = "bottom", + ratio = 0.4, + }, + }, +} + +return panel diff --git a/lua/copilot/config/root_dir.lua b/lua/copilot/config/root_dir.lua new file mode 100644 index 00000000..99325f97 --- /dev/null +++ b/lua/copilot/config/root_dir.lua @@ -0,0 +1,10 @@ +---@alias RootDirFuncOrString string | fun(): string + +local root_dir = { + ---@type RootDirFuncOrString + default = function() + return vim.fs.dirname(vim.fs.find(".git", { upward = true })[1]) + end, +} + +return root_dir diff --git a/lua/copilot/config/server.lua b/lua/copilot/config/server.lua new file mode 100644 index 00000000..b5d28789 --- /dev/null +++ b/lua/copilot/config/server.lua @@ -0,0 +1,13 @@ +---@class ServerConfig +---@field type string<'nodejs', 'binary'> Type of the server +---@field custom_server_filepath string|nil Path to the custom server file + +local server = { + ---@type ServerConfig + default = { + type = "nodejs", + custom_server_filepath = nil, + }, +} + +return server diff --git a/lua/copilot/config/should_attach.lua b/lua/copilot/config/should_attach.lua new file mode 100644 index 00000000..3089b837 --- /dev/null +++ b/lua/copilot/config/should_attach.lua @@ -0,0 +1,22 @@ +---@alias ShouldAttachFunc fun(bufnr: integer, bufname: string): boolean + +local logger = require("copilot.logger") + +local should_attach = { + ---@type ShouldAttachFunc + default = function(_, _) + if not vim.bo.buflisted then + logger.debug("not attaching, bugger is not 'buflisted'") + return false + end + + if vim.bo.buftype ~= "" then + logger.debug("not attaching, buffer 'buftype' is " .. vim.bo.buftype) + return false + end + + return true + end, +} + +return should_attach diff --git a/lua/copilot/config/suggestion.lua b/lua/copilot/config/suggestion.lua new file mode 100644 index 00000000..49543484 --- /dev/null +++ b/lua/copilot/config/suggestion.lua @@ -0,0 +1,34 @@ +---@class SuggestionConfig +---@field enabled boolean Whether to enable the suggestion +---@field auto_trigger boolean Whether to trigger the suggestion automatically +---@field hide_during_completion boolean Whether to hide the suggestion during completion +---@field debounce integer Debounce time in milliseconds +---@field keymap SuggestionKeymapConfig Keymap for the suggestion + +---@class SuggestionKeymapConfig +---@field accept string|false Keymap for accepting the suggestion +---@field accept_word string|false Keymap for accepting the word +---@field accept_line string|false Keymap for accepting the line +---@field next string|false Keymap for going to the next suggestion +---@field prev string|false Keymap for going to the previous suggestion +---@field dismiss string|false Keymap for dismissing the suggestion + +local suggestion = { + ---@type SuggestionConfig + default = { + enabled = true, + auto_trigger = false, + hide_during_completion = true, + debounce = 15, + keymap = { + accept = "", + accept_word = false, + accept_line = false, + next = "", + prev = "", + dismiss = "", + }, + }, +} + +return suggestion diff --git a/lua/copilot/init.lua b/lua/copilot/init.lua index 5e495f1a..eeadfadb 100644 --- a/lua/copilot/init.lua +++ b/lua/copilot/init.lua @@ -1,33 +1,9 @@ local M = { setup_done = false } -local config = require("copilot.config") local highlight = require("copilot.highlight") local logger = require("copilot.logger") local client = require("copilot.client") local auth = require("copilot.auth") - -local create_cmds = function() - vim.api.nvim_create_user_command("CopilotDetach", function() - if require("copilot.client").buf_is_attached(0) then - vim.deprecate("':CopilotDetach'", "':Copilot detach'", "in future", "copilot.lua") - vim.cmd("Copilot detach") - end - end, {}) - - vim.api.nvim_create_user_command("CopilotStop", function() - vim.deprecate("':CopilotStop'", "':Copilot disable'", "in future", "copilot.lua") - vim.cmd("Copilot disable") - end, {}) - - vim.api.nvim_create_user_command("CopilotPanel", function() - vim.deprecate("':CopilotPanel'", "':Copilot panel'", "in future", "copilot.lua") - vim.cmd("Copilot panel") - end, {}) - - vim.api.nvim_create_user_command("CopilotAuth", function() - vim.deprecate("':CopilotAuth'", "':Copilot auth'", "in future", "copilot.lua") - vim.cmd("Copilot auth") - end, {}) -end +local config = require("copilot.config") M.setup = function(opts) if M.setup_done then @@ -35,14 +11,10 @@ M.setup = function(opts) end highlight.setup() - - local conf = config.setup(opts) - if conf and conf.panel.enabled then - create_cmds() - end + config.merge_with_user_configs(opts) require("copilot.command").enable() - logger.setup(conf.logger) + logger.setup(config.logger) logger.debug("active plugin config:", config) -- logged here to ensure the logger is setup diff --git a/lua/copilot/logger.lua b/lua/copilot/logger/init.lua similarity index 64% rename from lua/copilot/logger.lua rename to lua/copilot/logger/init.lua index 68aee835..861a826d 100644 --- a/lua/copilot/logger.lua +++ b/lua/copilot/logger/init.lua @@ -1,7 +1,7 @@ local uv = vim.uv ---@class logger -local mod = { +local M = { log_file = vim.fn.stdpath("log") .. "/copilot-lua.log", file_log_level = vim.log.levels.OFF, print_log_level = vim.log.levels.WARN, @@ -29,14 +29,14 @@ end ---@return string log_msg local function format_log(log_level, msg, ...) local log_level_name = log_level_names[log_level] - mod.logger_id = mod.logger_id + 1 + M.logger_id = M.logger_id + 1 - if mod.logger_id > 1000000 then - mod.logger_id = 1 + if M.logger_id > 1000000 then + M.logger_id = 1 end -- we add an id as this process is asynchronous and the logs end up in a different order - local log_msg = string.format("%s [%d] [%s]: %s", get_timestamp_with_ms(), mod.logger_id, log_level_name, msg) + local log_msg = string.format("%s [%d] [%s]: %s", get_timestamp_with_ms(), M.logger_id, log_level_name, msg) local args = { ... } for _, v in ipairs(args) do @@ -80,84 +80,84 @@ end ---@param log_level integer -- one of the vim.log.levels ---@param msg string ---@param ... any -function mod.log(log_level, msg, ...) - mod.log_force(log_level, msg, false, ...) +function M.log(log_level, msg, ...) + M.log_force(log_level, msg, false, ...) end ---@param log_level integer -- one of the vim.log.levels ---@param msg string ---@param ... any ---@param force_print boolean -function mod.log_force(log_level, msg, force_print, ...) - if mod.file_log_level <= log_level then - write_log(log_level, mod.log_file, msg, ...) +function M.log_force(log_level, msg, force_print, ...) + if M.file_log_level <= log_level then + write_log(log_level, M.log_file, msg, ...) end - if force_print or (mod.print_log_level <= log_level) then + if force_print or (M.print_log_level <= log_level) then notify_log(log_level, msg, ...) end end ---@param msg string ---@param ... any -function mod.debug(msg, ...) - mod.log(vim.log.levels.DEBUG, msg, ...) +function M.debug(msg, ...) + M.log(vim.log.levels.DEBUG, msg, ...) end ---@param msg string ---@param ... any -function mod.trace(msg, ...) - mod.log(vim.log.levels.TRACE, msg, ...) +function M.trace(msg, ...) + M.log(vim.log.levels.TRACE, msg, ...) end ---@param msg string ---@param ... any -function mod.error(msg, ...) - mod.log(vim.log.levels.ERROR, msg, ...) +function M.error(msg, ...) + M.log(vim.log.levels.ERROR, msg, ...) end ---@param msg string ---@param ... any -function mod.warn(msg, ...) - mod.log(vim.log.levels.WARN, msg, ...) +function M.warn(msg, ...) + M.log(vim.log.levels.WARN, msg, ...) end ---@param msg string ---@param ... any -function mod.info(msg, ...) - mod.log(vim.log.levels.INFO, msg, ...) +function M.info(msg, ...) + M.log(vim.log.levels.INFO, msg, ...) end ---@param msg string ---@param ... any -function mod.notify(msg, ...) - mod.log_force(vim.log.levels.INFO, msg, true, ...) +function M.notify(msg, ...) + M.log_force(vim.log.levels.INFO, msg, true, ...) end ----@param conf copilot_config_logging -function mod.setup(conf) - mod.log_file = conf.file - mod.file_log_level = conf.file_log_level - mod.print_log_level = conf.print_log_level +---@param conf LoggerConfig +function M.setup(conf) + M.log_file = conf.file + M.file_log_level = conf.file_log_level + M.print_log_level = conf.print_log_level end -function mod.handle_lsp_trace(_, result, _) +function M.handle_lsp_trace(_, result, _) if not result then return end - mod.trace(string.format("LSP trace - %s", result.message), result.verbose) + M.trace(string.format("LSP trace - %s", result.message), result.verbose) end -function mod.handle_lsp_progress(_, result, _) +function M.handle_lsp_progress(_, result, _) if not result then return end - mod.trace(string.format("LSP progress - token %s", result.token), result.value) + M.trace(string.format("LSP progress - token %s", result.token), result.value) end -function mod.handle_log_lsp_messages(_, result, _) +function M.handle_log_lsp_messages(_, result, _) if not result then return end @@ -166,18 +166,18 @@ function mod.handle_log_lsp_messages(_, result, _) local message_type = result.type --[[@as integer]] if message_type == 1 then - mod.error(message) + M.error(message) elseif message_type == 2 then - mod.warn(message) + M.warn(message) elseif message_type == 3 then - mod.info(message) + M.info(message) elseif message_type == 4 then - mod.info(message) + M.info(message) elseif message_type == 5 then - mod.debug(message) + M.debug(message) else - mod.trace(message) + M.trace(message) end end -return mod +return M diff --git a/lua/copilot/lsp_binary.lua b/lua/copilot/lsp/binary.lua similarity index 100% rename from lua/copilot/lsp_binary.lua rename to lua/copilot/lsp/binary.lua diff --git a/lua/copilot/lsp/init.lua b/lua/copilot/lsp/init.lua new file mode 100644 index 00000000..93af098e --- /dev/null +++ b/lua/copilot/lsp/init.lua @@ -0,0 +1,6 @@ +local M = { + binary = require("copilot/lsp/binary"), + nodejs = require("copilot/lsp/nodejs"), +} + +return M diff --git a/lua/copilot/lsp_nodejs.lua b/lua/copilot/lsp/nodejs.lua similarity index 100% rename from lua/copilot/lsp_nodejs.lua rename to lua/copilot/lsp/nodejs.lua diff --git a/lua/copilot/panel.lua b/lua/copilot/panel/init.lua similarity index 99% rename from lua/copilot/panel.lua rename to lua/copilot/panel/init.lua index 8d1b0532..86129f5b 100644 --- a/lua/copilot/panel.lua +++ b/lua/copilot/panel/init.lua @@ -567,7 +567,7 @@ function mod.open(layout) end function mod.setup() - local opts = config.config.panel + local opts = config.panel if not opts.enabled then return end @@ -592,7 +592,7 @@ function mod.setup() end function mod.teardown() - local opts = config.config.panel + local opts = config.panel if not opts.enabled then return end diff --git a/lua/copilot/suggestion.lua b/lua/copilot/suggestion/init.lua similarity index 99% rename from lua/copilot/suggestion.lua rename to lua/copilot/suggestion/init.lua index b6147200..2e0bca96 100644 --- a/lua/copilot/suggestion.lua +++ b/lua/copilot/suggestion/init.lua @@ -702,7 +702,7 @@ local function create_autocmds() end function mod.setup() - local opts = config.config.suggestion + local opts = config.suggestion if not opts.enabled then return end @@ -723,7 +723,7 @@ function mod.setup() end function mod.teardown() - local opts = config.config.suggestion + local opts = config.suggestion if not opts.enabled then return end diff --git a/lua/copilot/util.lua b/lua/copilot/util.lua index 6f98dc68..63910f79 100644 --- a/lua/copilot/util.lua +++ b/lua/copilot/util.lua @@ -90,7 +90,7 @@ end ---@return boolean should_attach ---@return string? no_attach_reason function M.should_attach() - local ft = config.config.filetypes + local ft = config.filetypes local ft_disabled, ft_disabled_reason = is_ft_disabled(vim.bo.filetype, ft) if ft_disabled then @@ -169,14 +169,13 @@ end ---@return copilot_workspace_configurations function M.get_workspace_configurations() - local conf = config.config - local filetypes = vim.deepcopy(conf.filetypes) --[[@as table]] + local filetypes = vim.deepcopy(config.filetypes) --[[@as table]] if filetypes["*"] == nil then filetypes = vim.tbl_deep_extend("keep", filetypes, internal_filetypes) end - local copilot_model = conf and conf.copilot_model ~= "" and conf.copilot_model or "" + local copilot_model = config and config.copilot_model ~= "" and config.copilot_model or "" ---@type string[] local disabled_filetypes = vim.tbl_filter(function(ft) @@ -191,7 +190,7 @@ function M.get_workspace_configurations() selectedCompletionModel = copilot_model, }, }, - enableAutoCompletions = not not (conf.panel.enabled or conf.suggestion.enabled), + enableAutoCompletions = not not (config.panel.enabled or config.suggestion.enabled), disabledLanguages = vim.tbl_map(function(ft) return { languageId = ft } end, disabled_filetypes), diff --git a/lua/copilot/workspace.lua b/lua/copilot/workspace/init.lua similarity index 100% rename from lua/copilot/workspace.lua rename to lua/copilot/workspace/init.lua diff --git a/lua/copilot/workspace/utils.lua b/lua/copilot/workspace/utils.lua new file mode 100644 index 00000000..0d45e0b0 --- /dev/null +++ b/lua/copilot/workspace/utils.lua @@ -0,0 +1,57 @@ +local logger = require("copilot.logger") +local api = require("copilot.api") +local config = require("copilot.config") +local c = require("copilot.client") +local M = {} + +function M.add_workspace_folder(folder_path) + if type(folder_path) ~= "string" then + logger.error("workspace folder path must be a string") + return false + end + + if vim.fn.isdirectory(folder_path) ~= 1 then + logger.error("invalid workspace folder: " .. folder_path) + return false + end + + -- Normalize path + folder_path = vim.fn.fnamemodify(folder_path, ":p") + + --- @type workspace_folder + local workspace_folder = { + uri = vim.uri_from_fname(folder_path), + name = folder_path, + } + + local workspace_folders = config.workspace_folders + if not workspace_folders then + workspace_folders = {} + end + + for _, existing_folder in ipairs(workspace_folders) do + if existing_folder == folder_path then + return + end + end + + table.insert(workspace_folders, { folder_path }) + config.workspace_folders = workspace_folders + + local client = c.get() + if client and client.initialized then + api.notify(client, "workspace/didChangeWorkspaceFolders", { + event = { + added = { workspace_folder }, + removed = {}, + }, + }) + logger.notify("added workspace folder: " .. folder_path) + else + logger.notify("workspace folder will be added on next session: " .. folder_path) + end + + return true +end + +return M From 397a38de0e8c4169854d969af7b1f67f6d65f014 Mon Sep 17 00:00:00 2001 From: Antoine Gaudreau Simard Date: Sun, 30 Mar 2025 20:09:22 -0400 Subject: [PATCH 2/7] refactor: extract filetype-related utils --- lua/copilot/client/filetypes.lua | 80 +++++++++++++++++ lua/copilot/client/init.lua | 4 +- lua/copilot/client/utils.lua | 61 +++++++++++++ lua/copilot/util.lua | 144 +------------------------------ 4 files changed, 144 insertions(+), 145 deletions(-) create mode 100644 lua/copilot/client/filetypes.lua diff --git a/lua/copilot/client/filetypes.lua b/lua/copilot/client/filetypes.lua new file mode 100644 index 00000000..ebe68dbf --- /dev/null +++ b/lua/copilot/client/filetypes.lua @@ -0,0 +1,80 @@ +local M = {} + +local language_normalization_map = { + bash = "shellscript", + bst = "bibtex", + cs = "csharp", + cuda = "cuda-cpp", + dosbatch = "bat", + dosini = "ini", + gitcommit = "git-commit", + gitrebase = "git-rebase", + make = "makefile", + objc = "objective-c", + objcpp = "objective-cpp", + ps1 = "powershell", + raku = "perl6", + sh = "shellscript", + text = "plaintext", +} + +function M.language_for_file_type(filetype) + -- trim filetypes after dot, e.g. `yaml.gotexttmpl` -> `yaml` + local ft = string.gsub(filetype, "%..*", "") + if not ft or ft == "" then + ft = "text" + end + return language_normalization_map[ft] or ft +end + +local internal_filetypes = { + yaml = false, + markdown = false, + help = false, + gitcommit = false, + gitrebase = false, + hgcommit = false, + svn = false, + cvs = false, + ["."] = false, +} + +---@param filetype_enabled boolean|fun():boolean +local function resolve_filetype_enabled(filetype_enabled) + if type(filetype_enabled) == "function" then + return filetype_enabled() + end + return filetype_enabled +end + +---@param ft string +---@param filetypes table +---@return boolean ft_disabled +---@return string? ft_disabled_reason +function M.is_ft_disabled(ft, filetypes) + if filetypes[ft] ~= nil then + return not resolve_filetype_enabled(filetypes[ft]), + string.format("'filetype' %s rejected by config filetypes[%s]", ft, ft) + end + + local short_ft = string.gsub(ft, "%..*", "") + + if filetypes[short_ft] ~= nil then + return not resolve_filetype_enabled(filetypes[short_ft]), + string.format("'filetype' %s rejected by config filetypes[%s]", ft, short_ft) + end + + if filetypes["*"] ~= nil then + return not resolve_filetype_enabled(filetypes["*"]), + string.format("'filetype' %s rejected by config filetypes[%s]", ft, "*") + end + + if internal_filetypes[short_ft] ~= nil then + return not internal_filetypes[short_ft], + string.format("'filetype' %s rejected by internal_filetypes[%s]", ft, short_ft) + end + + return false +end + +return M diff --git a/lua/copilot/client/init.lua b/lua/copilot/client/init.lua index f271f8f3..14b79caa 100644 --- a/lua/copilot/client/init.lua +++ b/lua/copilot/client/init.lua @@ -272,7 +272,7 @@ local function prepare_client_config(overrides) name = "copilot", capabilities = capabilities, get_language_id = function(_, filetype) - return util.language_for_file_type(filetype) + return require("copilot.client.filetypes").language_for_file_type(filetype) end, on_init = function(client, initialize_result) if M.id == client.id then @@ -280,7 +280,7 @@ local function prepare_client_config(overrides) end vim.schedule(function() - local configurations = util.get_workspace_configurations() + local configurations = utils.get_workspace_configurations() api.notify_change_configuration(client, configurations) logger.trace("workspace configuration", configurations) diff --git a/lua/copilot/client/utils.lua b/lua/copilot/client/utils.lua index 757eab9c..45a774fe 100644 --- a/lua/copilot/client/utils.lua +++ b/lua/copilot/client/utils.lua @@ -1,3 +1,5 @@ +local config = require("copilot.config") +local logger = require("copilot.logger") local M = {} ---@param config_root_dir RootDirFuncOrString @@ -18,4 +20,63 @@ function M.get_root_dir(config_root_dir) return root_dir end +---@return copilot_workspace_configurations +function M.get_workspace_configurations() + local filetypes = vim.deepcopy(config.filetypes) --[[@as table]] + + if filetypes["*"] == nil then + filetypes = vim.tbl_deep_extend("keep", filetypes, require("copilot.client.filetypes").internal_filetypes) + end + + local copilot_model = config and config.copilot_model ~= "" and config.copilot_model or "" + + ---@type string[] + local disabled_filetypes = vim.tbl_filter(function(ft) + return filetypes[ft] == false + end, vim.tbl_keys(filetypes)) + table.sort(disabled_filetypes) + + return { + settings = { + github = { + copilot = { + selectedCompletionModel = copilot_model, + }, + }, + enableAutoCompletions = not not (config.panel.enabled or config.suggestion.enabled), + disabledLanguages = vim.tbl_map(function(ft) + return { languageId = ft } + end, disabled_filetypes), + }, + } +end + +---@return copilot_window_show_document_result +---@param result copilot_window_show_document +function M.show_document(_, result) + logger.trace("window/showDocument:", result) + local success, _ = pcall(vim.ui.open, result.uri) + if not success then + if vim.ui.open ~= nil then + vim.api.nvim_echo({ + { "window/showDocument" }, + { vim.inspect({ _, result }) }, + { "\n", "NONE" }, + }, true, {}) + error("Unsupported OS: vim.ui.open exists but failed to execute.") + else + vim.api.nvim_echo({ + { "window/showDocument" }, + { vim.inspect({ _, result }) }, + { "\n", "NONE" }, + }, true, {}) + error("Unsupported Version: vim.ui.open requires Neovim >= 0.10") + end + end + + return { + success = success, + } +end + return M diff --git a/lua/copilot/util.lua b/lua/copilot/util.lua index 63910f79..53393ced 100644 --- a/lua/copilot/util.lua +++ b/lua/copilot/util.lua @@ -3,12 +3,6 @@ local logger = require("copilot.logger") local M = {} -local id = 0 -function M.get_next_id() - id = id + 1 - return id -end - ---@return { editorInfo: copilot_editor_info, editorPluginInfo: copilot_editor_plugin_info } function M.get_editor_info() local info = { @@ -37,61 +31,11 @@ function M.get_copilot_lua_version() return copilot_lua_version end -local internal_filetypes = { - yaml = false, - markdown = false, - help = false, - gitcommit = false, - gitrebase = false, - hgcommit = false, - svn = false, - cvs = false, - ["."] = false, -} - ----@param filetype_enabled boolean|fun():boolean -local function resolve_filetype_enabled(filetype_enabled) - if type(filetype_enabled) == "function" then - return filetype_enabled() - end - return filetype_enabled -end - ----@param ft string ----@param filetypes table ----@return boolean ft_disabled ----@return string? ft_disabled_reason -local function is_ft_disabled(ft, filetypes) - if filetypes[ft] ~= nil then - return not resolve_filetype_enabled(filetypes[ft]), - string.format("'filetype' %s rejected by config filetypes[%s]", ft, ft) - end - - local short_ft = string.gsub(ft, "%..*", "") - - if filetypes[short_ft] ~= nil then - return not resolve_filetype_enabled(filetypes[short_ft]), - string.format("'filetype' %s rejected by config filetypes[%s]", ft, short_ft) - end - - if filetypes["*"] ~= nil then - return not resolve_filetype_enabled(filetypes["*"]), - string.format("'filetype' %s rejected by config filetypes[%s]", ft, "*") - end - - if internal_filetypes[short_ft] ~= nil then - return not internal_filetypes[short_ft], - string.format("'filetype' %s rejected by internal_filetypes[%s]", ft, short_ft) - end - - return false -end - ---@return boolean should_attach ---@return string? no_attach_reason function M.should_attach() local ft = config.filetypes - local ft_disabled, ft_disabled_reason = is_ft_disabled(vim.bo.filetype, ft) + local ft_disabled, ft_disabled_reason = require("copilot.client.filetypes").is_ft_disabled(vim.bo.filetype, ft) if ft_disabled then return not ft_disabled, ft_disabled_reason @@ -100,33 +44,6 @@ function M.should_attach() return true end -local language_normalization_map = { - bash = "shellscript", - bst = "bibtex", - cs = "csharp", - cuda = "cuda-cpp", - dosbatch = "bat", - dosini = "ini", - gitcommit = "git-commit", - gitrebase = "git-rebase", - make = "makefile", - objc = "objective-c", - objcpp = "objective-cpp", - ps1 = "powershell", - raku = "perl6", - sh = "shellscript", - text = "plaintext", -} - -function M.language_for_file_type(filetype) - -- trim filetypes after dot, e.g. `yaml.gotexttmpl` -> `yaml` - local ft = string.gsub(filetype, "%..*", "") - if not ft or ft == "" then - ft = "text" - end - return language_normalization_map[ft] or ft -end - local function relative_path(absolute) local relative = vim.fn.fnamemodify(absolute, ":.") if string.sub(relative, 0, 1) == "/" then @@ -167,37 +84,6 @@ function M.get_doc_params(overrides) return params end ----@return copilot_workspace_configurations -function M.get_workspace_configurations() - local filetypes = vim.deepcopy(config.filetypes) --[[@as table]] - - if filetypes["*"] == nil then - filetypes = vim.tbl_deep_extend("keep", filetypes, internal_filetypes) - end - - local copilot_model = config and config.copilot_model ~= "" and config.copilot_model or "" - - ---@type string[] - local disabled_filetypes = vim.tbl_filter(function(ft) - return filetypes[ft] == false - end, vim.tbl_keys(filetypes)) - table.sort(disabled_filetypes) - - return { - settings = { - github = { - copilot = { - selectedCompletionModel = copilot_model, - }, - }, - enableAutoCompletions = not not (config.panel.enabled or config.suggestion.enabled), - disabledLanguages = vim.tbl_map(function(ft) - return { languageId = ft } - end, disabled_filetypes), - }, - } -end - M.get_plugin_path = function() local copilot_path = vim.api.nvim_get_runtime_file("lua/copilot/init.lua", false)[1] if vim.fn.filereadable(copilot_path) ~= 0 then @@ -217,32 +103,4 @@ function M.strutf16len(str) end end ----@return copilot_window_show_document_result ----@param result copilot_window_show_document -function M.show_document(_, result) - logger.trace("window/showDocument:", result) - local success, _ = pcall(vim.ui.open, result.uri) - if not success then - if vim.ui.open ~= nil then - vim.api.nvim_echo({ - { "window/showDocument" }, - { vim.inspect({ _, result }) }, - { "\n", "NONE" }, - }, true, {}) - error("Unsupported OS: vim.ui.open exists but failed to execute.") - else - vim.api.nvim_echo({ - { "window/showDocument" }, - { vim.inspect({ _, result }) }, - { "\n", "NONE" }, - }, true, {}) - error("Unsupported Version: vim.ui.open requires Neovim >= 0.10") - end - end - - return { - success = success, - } -end - return M From d93f32b7b85d1f102288f15d22bc9703e0e9b065 Mon Sep 17 00:00:00 2001 From: Antoine Gaudreau Simard Date: Mon, 31 Mar 2025 11:20:26 -0400 Subject: [PATCH 3/7] refactor: split out files further --- lua/copilot/api/init.lua | 149 +++++------------------ lua/copilot/client/config.lua | 156 ++++++++++++++++++++++++ lua/copilot/client/handlers.lua | 41 +++++++ lua/copilot/client/init.lua | 187 ++--------------------------- lua/copilot/command.lua | 99 ++------------- lua/copilot/highlight.lua | 10 +- lua/copilot/panel/handlers.lua | 45 +++++++ lua/copilot/panel/init.lua | 46 +++---- lua/copilot/status/init.lua | 118 ++++++++++++++++++ lua/copilot/suggestion/init.lua | 50 ++++---- lua/copilot/suggestion/keymaps.lua | 0 lua/copilot/workspace/init.lua | 10 +- plugin/copilot.lua | 2 + 13 files changed, 469 insertions(+), 444 deletions(-) create mode 100644 lua/copilot/client/config.lua create mode 100644 lua/copilot/client/handlers.lua create mode 100644 lua/copilot/panel/handlers.lua create mode 100644 lua/copilot/status/init.lua create mode 100644 lua/copilot/suggestion/keymaps.lua diff --git a/lua/copilot/api/init.lua b/lua/copilot/api/init.lua index 3c27f1e7..997fbf38 100644 --- a/lua/copilot/api/init.lua +++ b/lua/copilot/api/init.lua @@ -1,11 +1,12 @@ local logger = require("copilot.logger") -local mod = {} +---@class CopilotApi +local M = {} ---@param callback? fun(err: any|nil, data: table, ctx: table): nil ---@return any|nil err ---@return any data ---@return table ctx -function mod.request(client, method, params, callback) +function M.request(client, method, params, callback) logger.trace("api request:", method, params) -- hack to convert empty table to json object, -- empty table is convert to json array by default. @@ -26,7 +27,7 @@ function mod.request(client, method, params, callback) end ---@return boolean sent -function mod.notify(client, method, params) +function M.notify(client, method, params) logger.trace("api notify:", method, params) if vim.fn.has("nvim-0.11") == 1 then @@ -50,15 +51,15 @@ end ---@alias copilot_workspace_configurations { settings: copilot_workspace_configuration } ---@param params copilot_workspace_configurations -function mod.notify_change_configuration(client, params) - return mod.notify(client, "workspace/didChangeConfiguration", params) +function M.notify_change_configuration(client, params) + return M.notify(client, "workspace/didChangeConfiguration", params) end ---@alias copilot_nofify_set_trace_params { value: 'off'|'messages'|'verbose' } ---@param params copilot_nofify_set_trace_params -function mod.notify_set_trace(client, params) - return mod.notify(client, "$/setTrace", params) +function M.notify_set_trace(client, params) + return M.notify(client, "$/setTrace", params) end ---@alias copilot_check_status_params { options?: { localChecksOnly?: boolean } } @@ -68,12 +69,12 @@ end ---@return any|nil err ---@return copilot_check_status_data data ---@return table ctx -function mod.check_status(client, params, callback) +function M.check_status(client, params, callback) if type(params) == "function" then callback = params params = {} end - return mod.request(client, "checkStatus", params or {}, callback) + return M.request(client, "checkStatus", params or {}, callback) end ---@alias copilot_sign_in_initiate_data { verificationUri?: string, userCode?: string } @@ -81,8 +82,8 @@ end ---@return any|nil err ---@return copilot_sign_in_initiate_data data ---@return table ctx -function mod.sign_in_initiate(client, callback) - return mod.request(client, "signInInitiate", {}, callback) +function M.sign_in_initiate(client, callback) + return M.request(client, "signInInitiate", {}, callback) end ---@alias copilot_sign_in_confirm_params { userId: string } @@ -92,12 +93,12 @@ end ---@return any|nil err ---@return copilot_sign_in_confirm_data data ---@return table ctx -function mod.sign_in_confirm(client, params, callback) - return mod.request(client, "signInConfirm", params, callback) +function M.sign_in_confirm(client, params, callback) + return M.request(client, "signInConfirm", params, callback) end -function mod.sign_out(client, callback) - return mod.request(client, "signOut", {}, callback) +function M.sign_out(client, callback) + return M.request(client, "signOut", {}, callback) end ---@alias copilot_get_version_data { version: string } @@ -105,29 +106,29 @@ end ---@return any|nil err ---@return copilot_get_version_data data ---@return table ctx -function mod.get_version(client, callback) - return mod.request(client, "getVersion", {}, callback) +function M.get_version(client, callback) + return M.request(client, "getVersion", {}, callback) end ---@alias copilot_notify_accepted_params { uuid: string, acceptedLength?: integer } ---@param params copilot_notify_accepted_params -function mod.notify_accepted(client, params, callback) - return mod.request(client, "notifyAccepted", params, callback) +function M.notify_accepted(client, params, callback) + return M.request(client, "notifyAccepted", params, callback) end ---@alias copilot_notify_rejected_params { uuids: string[] } ---@param params copilot_notify_rejected_params -function mod.notify_rejected(client, params, callback) - return mod.request(client, "notifyRejected", params, callback) +function M.notify_rejected(client, params, callback) + return M.request(client, "notifyRejected", params, callback) end ---@alias copilot_notify_shown_params { uuid: string } ---@param params copilot_notify_shown_params -function mod.notify_shown(client, params, callback) - return mod.request(client, "notifyShown", params, callback) +function M.notify_shown(client, params, callback) + return M.request(client, "notifyShown", params, callback) end ---@alias copilot_get_completions_data_completion { displayText: string, position: { character: integer, line: integer }, range: { ['end']: { character: integer, line: integer }, start: { character: integer, line: integer } }, text: string, uuid: string } @@ -136,110 +137,22 @@ end ---@return any|nil err ---@return copilot_get_completions_data data ---@return table ctx -function mod.get_completions(client, params, callback) - return mod.request(client, "getCompletions", params, callback) +function M.get_completions(client, params, callback) + return M.request(client, "getCompletions", params, callback) end -function mod.get_completions_cycling(client, params, callback) - return mod.request(client, "getCompletionsCycling", params, callback) +function M.get_completions_cycling(client, params, callback) + return M.request(client, "getCompletionsCycling", params, callback) end ----@alias copilot_panel_solution_data { panelId: string, completionText: string, displayText: string, range: { ['end']: { character: integer, line: integer }, start: { character: integer, line: integer } }, score: number, solutionId: string } ----@alias copilot_panel_on_solution_handler fun(result: copilot_panel_solution_data): nil ----@alias copilot_panel_solutions_done_data { panelId: string, status: 'OK'|'Error', message?: string } ----@alias copilot_panel_on_solutions_done_handler fun(result: copilot_panel_solutions_done_data): nil - ---@return any|nil err ---@return integer data ---@return table ctx -function mod.get_panel_completions(client, params, callback) - return mod.request(client, "getPanelCompletions", params, callback) -end - -local panel = { - callback = { - PanelSolution = {}, - PanelSolutionsDone = {}, - }, -} - -panel.handlers = { - ---@param result copilot_panel_solution_data - PanelSolution = function(_, result) - if panel.callback.PanelSolution[result.panelId] then - panel.callback.PanelSolution[result.panelId](result) - end - end, - - ---@param result copilot_panel_solutions_done_data - PanelSolutionsDone = function(_, result) - if panel.callback.PanelSolutionsDone[result.panelId] then - panel.callback.PanelSolutionsDone[result.panelId](result) - end - end, -} - ----@param panelId string ----@param handlers { on_solution: copilot_panel_on_solution_handler, on_solutions_done: copilot_panel_on_solutions_done_handler } -function mod.register_panel_handlers(panelId, handlers) - assert(type(panelId) == "string", "missing panelId") - panel.callback.PanelSolution[panelId] = handlers.on_solution - panel.callback.PanelSolutionsDone[panelId] = handlers.on_solutions_done -end - ----@param panelId string -function mod.unregister_panel_handlers(panelId) - assert(type(panelId) == "string", "missing panelId") - panel.callback.PanelSolution[panelId] = nil - panel.callback.PanelSolutionsDone[panelId] = nil -end - ----@alias copilot_status_notification_data { status: ''|'Normal'|'InProgress'|'Warning', message: string } - -local status = { - client_id = nil, - ---@type copilot_status_notification_data - data = { - status = "", - message = "", - }, - callback = {}, -} - -status.handlers = { - ---@param result copilot_status_notification_data - ---@param ctx { client_id: integer, method: string } - statusNotification = function(_, result, ctx) - status.client_id = ctx.client_id - status.data = result - - for callback in pairs(status.callback) do - callback(status.data) - end - end, -} - ----@param handler fun(data: copilot_status_notification_data): nil -function mod.register_status_notification_handler(handler) - status.callback[handler] = true - handler(status.data) -end - ----@param handler fun(data: copilot_status_notification_data): nil -function mod.unregister_status_notification_handler(handler) - status.callback[handler] = nil +function M.get_panel_completions(client, params, callback) + return M.request(client, "getPanelCompletions", params, callback) end ---@alias copilot_window_show_document { uri: string, external?: boolean, takeFocus?: boolean, selection?: boolean } ---@alias copilot_window_show_document_result { success: boolean } -mod.handlers = { - PanelSolution = panel.handlers.PanelSolution, - PanelSolutionsDone = panel.handlers.PanelSolutionsDone, - statusNotification = status.handlers.statusNotification, -} - -mod.panel = panel -mod.status = status - -return mod +return M diff --git a/lua/copilot/client/config.lua b/lua/copilot/client/config.lua new file mode 100644 index 00000000..a27bb4c4 --- /dev/null +++ b/lua/copilot/client/config.lua @@ -0,0 +1,156 @@ +local api = require("copilot.api") +local config = require("copilot.config") +local util = require("copilot.util") +local logger = require("copilot.logger") +local lsp = require("copilot.lsp") +local utils = require("copilot.client.utils") +local M = {} + +---@param overrides table +---@param client CopilotClient +function M.prepare_client_config(overrides, client) + if lsp.binary.initialization_failed then + client.startup_error = "initialization of copilot-language-server failed" + return + end + + client.startup_error = nil + + local server_path = nil + local cmd = nil + + if config.server.custom_server_filepath and vim.fn.filereadable(config.server.custom_server_filepath) then + server_path = config.server.custom_server_filepath + end + + if config.server.type == "nodejs" then + cmd = { + lsp.nodejs.node_command, + server_path or lsp.nodejs.get_server_path(), + "--stdio", + } + elseif config.server.type == "binary" then + cmd = { + server_path or lsp.binary.get_server_path(), + "--stdio", + } + end + + if not cmd then + logger.error("copilot server type not supported") + return + end + + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities.window.showDocument.support = true + + capabilities.workspace = { + workspaceFolders = true, + } + + local root_dir = utils.get_root_dir(config.root_dir) + local workspace_folders = { + --- @type workspace_folder + { + uri = vim.uri_from_fname(root_dir), + -- important to keep root_dir as-is for the name as lsp.lua uses this to check the workspace has not changed + name = root_dir, + }, + } + + local config_workspace_folders = config.workspace_folders + + for _, config_workspace_folder in ipairs(config_workspace_folders) do + if config_workspace_folder ~= "" then + table.insert( + workspace_folders, + --- @type workspace_folder + { + uri = vim.uri_from_fname(config_workspace_folder), + name = config_workspace_folder, + } + ) + end + end + + local editor_info = util.get_editor_info() + local provider_url = config.auth_provider_url + local proxy_uri = vim.g.copilot_proxy + + local settings = { ---@type copilot_settings + telemetry = { ---@type github_settings_telemetry + telemetryLevel = "all", + }, + } + + if proxy_uri then + vim.tbl_extend("force", settings, { + http = { ---@type copilot_settings_http + proxy = proxy_uri, + proxyStrictSSL = vim.g.copilot_proxy_strict_ssl or false, + proxyKerberosServicePrincipal = nil, + }, + }) + end + + if provider_url then + vim.tbl_extend("force", settings, { + ["github-enterprise"] = { ---@type copilot_settings_github-enterprise + uri = provider_url, + }, + }) + end + + -- LSP config, not to be confused with config.lua + return vim.tbl_deep_extend("force", { + cmd = cmd, + root_dir = root_dir, + name = "copilot", + capabilities = capabilities, + get_language_id = function(_, filetype) + return require("copilot.client.filetypes").language_for_file_type(filetype) + end, + on_init = function(lsp_client, initialize_result) + if client.id == lsp_client.id then + client.capabilities = initialize_result.capabilities + end + + vim.schedule(function() + local configurations = utils.get_workspace_configurations() + api.notify_change_configuration(lsp_client, configurations) + logger.trace("workspace configuration", configurations) + + -- to activate tracing if we want it + local logger_conf = config.logger + local trace_params = { value = logger_conf.trace_lsp } --[[@as copilot_nofify_set_trace_params]] + api.notify_set_trace(lsp_client, trace_params) + + -- prevent requests to copilot prior to being initialized + client.initialized = true + end) + end, + on_exit = function(code, _, client_id) + if client.id == client_id then + vim.schedule(function() + client.teardown() + client.id = nil + client.capabilities = nil + end) + end + if code > 0 then + vim.schedule(function() + require("copilot.command").status() + end) + end + end, + handlers = require("copilot.client.handlers").get_handlers(), + init_options = { + editorInfo = editor_info.editorInfo, + editorPluginInfo = editor_info.editorPluginInfo, + }, + settings = settings, + workspace_folders = workspace_folders, + }, overrides) +end + +return M diff --git a/lua/copilot/client/handlers.lua b/lua/copilot/client/handlers.lua new file mode 100644 index 00000000..58b79174 --- /dev/null +++ b/lua/copilot/client/handlers.lua @@ -0,0 +1,41 @@ +local config = require("copilot.config") +local util = require("copilot.util") +local logger = require("copilot.logger") +local status = require("copilot.status") +local panel = require("copilot.panel") + +local M = {} + +function M.get_handlers() + local handlers = { + -- TODO: I don't like the handlers.handlers + PanelSolution = panel.handlers.handlers.PanelSolution, + PanelSolutionsDone = panel.handlers.handlers.PanelSolutionsDone, + statusNotification = status.handlers.statusNotification, + ["window/showDocument"] = util.show_document, + } + + -- optional handlers + local logger_conf = config.logger + if logger_conf.trace_lsp ~= "off" then + handlers = vim.tbl_extend("force", handlers, { + ["$/logTrace"] = logger.handle_lsp_trace, + }) + end + + if logger_conf.trace_lsp_progress then + handlers = vim.tbl_extend("force", handlers, { + ["$/progress"] = logger.handle_lsp_progress, + }) + end + + if logger_conf.log_lsp_messages then + handlers = vim.tbl_extend("force", handlers, { + ["window/logMessage"] = logger.handle_log_lsp_messages, + }) + end + + return handlers +end + +return M diff --git a/lua/copilot/client/init.lua b/lua/copilot/client/init.lua index 14b79caa..478f80df 100644 --- a/lua/copilot/client/init.lua +++ b/lua/copilot/client/init.lua @@ -1,4 +1,3 @@ -local api = require("copilot.api") local config = require("copilot.config") local util = require("copilot.util") local logger = require("copilot.logger") @@ -7,11 +6,15 @@ local utils = require("copilot.client.utils") local is_disabled = false +---@class CopilotClient +---@field id integer|nil +---@field capabilities lsp.ClientCapabilities | nil +---@field config vim.lsp.ClientConfig | nil +---@field startup_error string | nil +---@field initialized boolean local M = { augroup = "copilot.client", id = nil, - --- @class copilot_capabilities:lsp.ClientCapabilities - --- @field workspace table<'workspaceFolders', boolean> capabilities = nil, config = nil, startup_error = nil, @@ -141,182 +144,6 @@ function M.use_client(callback) ) end -local function get_handlers() - local handlers = { - PanelSolution = api.handlers.PanelSolution, - PanelSolutionsDone = api.handlers.PanelSolutionsDone, - statusNotification = api.handlers.statusNotification, - ["window/showDocument"] = util.show_document, - } - - -- optional handlers - local logger_conf = config.logger - if logger_conf.trace_lsp ~= "off" then - handlers = vim.tbl_extend("force", handlers, { - ["$/logTrace"] = logger.handle_lsp_trace, - }) - end - - if logger_conf.trace_lsp_progress then - handlers = vim.tbl_extend("force", handlers, { - ["$/progress"] = logger.handle_lsp_progress, - }) - end - - if logger_conf.log_lsp_messages then - handlers = vim.tbl_extend("force", handlers, { - ["window/logMessage"] = logger.handle_log_lsp_messages, - }) - end - - return handlers -end - -local function prepare_client_config(overrides) - if lsp.binary.initialization_failed then - M.startup_error = "initialization of copilot-language-server failed" - return - end - - M.startup_error = nil - - local server_path = nil - local cmd = nil - - if config.server.custom_server_filepath and vim.fn.filereadable(config.server.custom_server_filepath) then - server_path = config.server.custom_server_filepath - end - - if config.server.type == "nodejs" then - cmd = { - lsp.nodejs.node_command, - server_path or lsp.nodejs.get_server_path(), - "--stdio", - } - elseif config.server.type == "binary" then - cmd = { - server_path or lsp.binary.get_server_path(), - "--stdio", - } - end - - if not cmd then - logger.error("copilot server type not supported") - return - end - - local capabilities = vim.lsp.protocol.make_client_capabilities() --[[@as copilot_capabilities]] - capabilities.window.showDocument.support = true - - capabilities.workspace = { - workspaceFolders = true, - } - - local root_dir = utils.get_root_dir(config.root_dir) - local workspace_folders = { - --- @type workspace_folder - { - uri = vim.uri_from_fname(root_dir), - -- important to keep root_dir as-is for the name as lsp.lua uses this to check the workspace has not changed - name = root_dir, - }, - } - - local config_workspace_folders = config.workspace_folders - - for _, config_workspace_folder in ipairs(config_workspace_folders) do - if config_workspace_folder ~= "" then - table.insert( - workspace_folders, - --- @type workspace_folder - { - uri = vim.uri_from_fname(config_workspace_folder), - name = config_workspace_folder, - } - ) - end - end - - local editor_info = util.get_editor_info() - local provider_url = config.auth_provider_url - local proxy_uri = vim.g.copilot_proxy - - local settings = { ---@type copilot_settings - telemetry = { ---@type github_settings_telemetry - telemetryLevel = "all", - }, - } - - if proxy_uri then - vim.tbl_extend("force", settings, { - http = { ---@type copilot_settings_http - proxy = proxy_uri, - proxyStrictSSL = vim.g.copilot_proxy_strict_ssl or false, - proxyKerberosServicePrincipal = nil, - }, - }) - end - - if provider_url then - vim.tbl_extend("force", settings, { - ["github-enterprise"] = { ---@type copilot_settings_github-enterprise - uri = provider_url, - }, - }) - end - - -- LSP config, not to be confused with config.lua - return vim.tbl_deep_extend("force", { - cmd = cmd, - root_dir = root_dir, - name = "copilot", - capabilities = capabilities, - get_language_id = function(_, filetype) - return require("copilot.client.filetypes").language_for_file_type(filetype) - end, - on_init = function(client, initialize_result) - if M.id == client.id then - M.capabilities = initialize_result.capabilities - end - - vim.schedule(function() - local configurations = utils.get_workspace_configurations() - api.notify_change_configuration(client, configurations) - logger.trace("workspace configuration", configurations) - - -- to activate tracing if we want it - local logger_conf = config.logger - local trace_params = { value = logger_conf.trace_lsp } --[[@as copilot_nofify_set_trace_params]] - api.notify_set_trace(client, trace_params) - - -- prevent requests to copilot prior to being initialized - M.initialized = true - end) - end, - on_exit = function(code, _, client_id) - if M.id == client_id then - vim.schedule(function() - M.teardown() - M.id = nil - M.capabilities = nil - end) - end - if code > 0 then - vim.schedule(function() - require("copilot.command").status() - end) - end - end, - handlers = get_handlers(), - init_options = { - editorInfo = editor_info.editorInfo, - editorPluginInfo = editor_info.editorPluginInfo, - }, - settings = settings, - workspace_folders = workspace_folders, - }, overrides) -end - function M.setup() local node_command = config.copilot_node_command @@ -327,7 +154,7 @@ function M.setup() lsp.binary.setup(config.server.custom_server_filepath) end - M.config = prepare_client_config(config.server_opts_overrides) + M.config = require("copilot.client.config").prepare_client_config(config.server_opts_overrides, M) if not M.config then is_disabled = true diff --git a/lua/copilot/command.lua b/lua/copilot/command.lua index 92d6aff5..0085e798 100644 --- a/lua/copilot/command.lua +++ b/lua/copilot/command.lua @@ -2,9 +2,9 @@ local a = require("copilot.api") local c = require("copilot.client") local u = require("copilot.util") -local mod = {} +local M = {} -function mod.version() +function M.version() local info = u.get_editor_info() ---@type (string|table)[] @@ -17,6 +17,7 @@ function mod.version() local client = c.get() coroutine.wrap(function() + -- TODO: this is now in lsp/* local copilot_server_info = u.get_copilot_server_info() if client then local _, data = a.get_version(client) @@ -35,89 +36,13 @@ function mod.version() end)() end -function mod.status() - local lines = {} - - local function add_line(line) - if not line then - return - end - - lines[#lines + 1] = type(line) == "table" and { "[Copilot] " .. line[1], line[2] } or { "[Copilot] " .. line } - lines[#lines + 1] = { "\n", "NONE" } - end - - local function flush_lines(last_line) - add_line(last_line) - - if c.startup_error then - add_line({ c.startup_error, "WarningMsg" }) - end - - vim.api.nvim_echo(lines, true, {}) - end - - if c.is_disabled() then - flush_lines("Offline") - return - end - - local client = c.get() - if not client then - flush_lines("Not Started") - return - end - - add_line("Online") - - coroutine.wrap(function() - local cserr, status = a.check_status(client) - if cserr then - flush_lines(cserr) - return - end - - if not status.user then - flush_lines("Not authenticated. Run ':Copilot auth'") - return - elseif status.status == "NoTelemetryConsent" then - flush_lines("Telemetry terms not accepted") - return - elseif status.status == "NotAuthorized" then - flush_lines("Not authorized") - return - end - - local should_attach, no_attach_reason = u.should_attach() - local is_attached = c.buf_is_attached() - if is_attached then - if not should_attach then - add_line("Enabled manually (" .. no_attach_reason .. ")") - else - add_line("Enabled for " .. vim.bo.filetype) - end - elseif not is_attached then - if should_attach then - add_line("Disabled manually for " .. vim.bo.filetype) - else - add_line("Disabled (" .. no_attach_reason .. ")") - end - end - - if string.lower(a.status.data.status) == "error" then - add_line(a.status.data.message) - end - - flush_lines() - end)() -end - ---@param opts? { force?: boolean } -function mod.attach(opts) +function M.attach(opts) opts = opts or {} if not opts.force then local should_attach, no_attach_reason = u.should_attach() + -- TODO: add other should_attach method here if not should_attach then vim.api.nvim_echo({ { "[Copilot] " .. no_attach_reason .. "\n" }, @@ -132,34 +57,34 @@ function mod.attach(opts) c.buf_attach(opts.force) end -function mod.detach() +function M.detach() if c.buf_is_attached(0) then c.buf_detach() end end ---@param opts? { force?: boolean } -function mod.toggle(opts) +function M.toggle(opts) opts = opts or {} if c.buf_is_attached(0) then - mod.detach() + M.detach() return end - mod.attach(opts) + M.attach(opts) end -function mod.enable() +function M.enable() c.setup() require("copilot.panel").setup() require("copilot.suggestion").setup() end -function mod.disable() +function M.disable() c.teardown() require("copilot.panel").teardown() require("copilot.suggestion").teardown() end -return mod +return M diff --git a/lua/copilot/highlight.lua b/lua/copilot/highlight.lua index 55197ed5..edc9a844 100644 --- a/lua/copilot/highlight.lua +++ b/lua/copilot/highlight.lua @@ -1,4 +1,4 @@ -local mod = { +local M = { group = { CopilotAnnotation = "CopilotAnnotation", CopilotSuggestion = "CopilotSuggestion", @@ -6,11 +6,11 @@ local mod = { } local links = { - [mod.group.CopilotAnnotation] = "Comment", - [mod.group.CopilotSuggestion] = "Comment", + [M.group.CopilotAnnotation] = "Comment", + [M.group.CopilotSuggestion] = "Comment", } -function mod.setup() +function M.setup() -- Some environments will load themes after plugins (like ChadNv) so we do it as late as possible vim.schedule(function() for from_group, to_group in pairs(links) do @@ -22,4 +22,4 @@ function mod.setup() end) end -return mod +return M diff --git a/lua/copilot/panel/handlers.lua b/lua/copilot/panel/handlers.lua new file mode 100644 index 00000000..74ea1f3b --- /dev/null +++ b/lua/copilot/panel/handlers.lua @@ -0,0 +1,45 @@ +local M = { + callback = { + PanelSolution = {}, + PanelSolutionsDone = {}, + }, + handlers = {}, +} + +---@alias copilot_panel_solution_data { panelId: string, completionText: string, displayText: string, range: { ['end']: { character: integer, line: integer }, start: { character: integer, line: integer } }, score: number, solutionId: string } +---@alias copilot_panel_on_solution_handler fun(result: copilot_panel_solution_data): nil +---@alias copilot_panel_solutions_done_data { panelId: string, status: 'OK'|'Error', message?: string } +---@alias copilot_panel_on_solutions_done_handler fun(result: copilot_panel_solutions_done_data): nil + +M.handlers = { + ---@param result copilot_panel_solution_data + PanelSolution = function(_, result) + if M.callback.PanelSolution[result.panelId] then + M.callback.PanelSolution[result.panelId](result) + end + end, + + ---@param result copilot_panel_solutions_done_data + PanelSolutionsDone = function(_, result) + if M.callback.PanelSolutionsDone[result.panelId] then + M.callback.PanelSolutionsDone[result.panelId](result) + end + end, +} + +---@param panelId string +---@param handlers { on_solution: copilot_panel_on_solution_handler, on_solutions_done: copilot_panel_on_solutions_done_handler } +function M.register_panel_handlers(panelId, handlers) + assert(type(panelId) == "string", "missing panelId") + M.callback.PanelSolution[panelId] = handlers.on_solution + M.callback.PanelSolutionsDone[panelId] = handlers.on_solutions_done +end + +---@param panelId string +function M.unregister_panel_handlers(panelId) + assert(type(panelId) == "string", "missing panelId") + M.callback.PanelSolution[panelId] = nil + M.callback.PanelSolutionsDone[panelId] = nil +end + +return M diff --git a/lua/copilot/panel/init.lua b/lua/copilot/panel/init.lua index 86129f5b..cfb9b499 100644 --- a/lua/copilot/panel/init.lua +++ b/lua/copilot/panel/init.lua @@ -5,10 +5,10 @@ local hl_group = require("copilot.highlight").group local util = require("copilot.util") local logger = require("copilot.logger") -local mod = {} - +local M = { + handlers = require("copilot.panel.handlers"), +} local marker_prefix = "[copilot] " - local panel_uri_prefix = "copilot://" local panel = { @@ -259,7 +259,7 @@ end local function set_keymap(bufnr) if panel.keymap.accept then - vim.keymap.set("n", panel.keymap.accept, mod.accept, { + vim.keymap.set("n", panel.keymap.accept, M.accept, { buffer = bufnr, desc = "[copilot] (panel) accept", silent = true, @@ -267,7 +267,7 @@ local function set_keymap(bufnr) end if panel.keymap.jump_prev then - vim.keymap.set("n", panel.keymap.jump_prev, mod.jump_prev, { + vim.keymap.set("n", panel.keymap.jump_prev, M.jump_prev, { buffer = bufnr, desc = "[copilot] (panel) jump prev", silent = true, @@ -275,7 +275,7 @@ local function set_keymap(bufnr) end if panel.keymap.jump_next then - vim.keymap.set("n", panel.keymap.jump_next, mod.jump_next, { + vim.keymap.set("n", panel.keymap.jump_next, M.jump_next, { buffer = bufnr, desc = "[copilot] (panel) jump next", silent = true, @@ -283,7 +283,7 @@ local function set_keymap(bufnr) end if panel.keymap.refresh then - vim.keymap.set("n", panel.keymap.refresh, mod.refresh, { + vim.keymap.set("n", panel.keymap.refresh, M.refresh, { buffer = bufnr, desc = "[copilot] (panel) refresh", silent = true, @@ -412,7 +412,7 @@ function panel:refresh() end if self.panelId then - api.unregister_panel_handlers(self.panelId) + M.handlers.unregister_panel_handlers(self.panelId) end if self.state.req_id then @@ -423,11 +423,11 @@ function panel:refresh() self.req_number = self.req_number + 1 self.panelId = self.req_number .. ":" .. self.panel_uri - api.register_panel_handlers(self.panelId, { + M.handlers.register_panel_handlers(self.panelId, { ---@param result copilot_panel_solution_data on_solution = function(result) if result.panelId ~= self.panelId then - api.unregister_panel_handlers(result.panelId) + M.handlers.unregister_panel_handlers(result.panelId) return end @@ -439,7 +439,7 @@ function panel:refresh() self.state.req_id = nil if result.panelId ~= self.panelId then - api.unregister_panel_handlers(result.panelId) + M.handlers.unregister_panel_handlers(result.panelId) return end @@ -502,7 +502,7 @@ function panel:init() if is_panel_uri(doc.uri) then -- currently inside the panel itself - mod.refresh() + M.refresh() return end @@ -524,27 +524,27 @@ function panel:init() vim.api.nvim_set_current_win(self.winid) end -function mod.accept() +function M.accept() panel:accept() end -function mod.jump_prev() +function M.jump_prev() panel:jump(-1) end -function mod.jump_next() +function M.jump_next() panel:jump(1) end -function mod.toggle() +function M.toggle() if panel.winid and vim.api.nvim_win_is_valid(panel.winid) then panel:close() else - mod.open({}) + M.open({}) end end -function mod.refresh() +function M.refresh() vim.api.nvim_buf_call(vim.uri_to_bufnr(panel_uri_to_doc_uri(panel.panel_uri)), function() panel:refresh() end) @@ -553,7 +553,7 @@ end ---@param layout {position: string, ratio: number} ---position: (optional) 'bottom' | 'top' | 'left' | 'right' | 'horizontal' | 'vertical' ---ratio: (optional) between 0 and 1 -function mod.open(layout) +function M.open(layout) local client = c.get() if not client then logger.error("copilot is not running") @@ -566,7 +566,7 @@ function mod.open(layout) panel:init() end -function mod.setup() +function M.setup() local opts = config.panel if not opts.enabled then return @@ -582,7 +582,7 @@ function mod.setup() panel.layout = vim.tbl_deep_extend("force", panel.layout, opts.layout or {}) if panel.keymap.open then - vim.keymap.set("i", panel.keymap.open, mod.open, { + vim.keymap.set("i", panel.keymap.open, M.open, { desc = "[copilot] (panel) open", silent = true, }) @@ -591,7 +591,7 @@ function mod.setup() panel.setup_done = true end -function mod.teardown() +function M.teardown() local opts = config.panel if not opts.enabled then return @@ -610,4 +610,4 @@ function mod.teardown() panel.setup_done = false end -return mod +return M diff --git a/lua/copilot/status/init.lua b/lua/copilot/status/init.lua new file mode 100644 index 00000000..99b0bd90 --- /dev/null +++ b/lua/copilot/status/init.lua @@ -0,0 +1,118 @@ +local u = require("copilot.util") +local c = require("copilot.client") +local a = require("copilot.api") +---@alias copilot_status_notification_data { status: ''|'Normal'|'InProgress'|'Warning', message: string } + +local M = { + client_id = nil, + ---@type copilot_status_notification_data + data = { + status = "", + message = "", + }, + callback = {}, + handlers = {}, +} + +M.handlers = { + ---@param result copilot_status_notification_data + ---@param ctx { client_id: integer, method: string } + statusNotification = function(_, result, ctx) + M.client_id = ctx.client_id + M.data = result + + for callback in pairs(M.callback) do + callback(M.data) + end + end, +} + +---@param handler fun(data: copilot_status_notification_data): nil +function M.register_status_notification_handler(handler) + M.callback[handler] = true + handler(M.data) +end + +---@param handler fun(data: copilot_status_notification_data): nil +function M.unregister_status_notification_handler(handler) + M.callback[handler] = nil +end + +function M.status() + local lines = {} + + local function add_line(line) + if not line then + return + end + + lines[#lines + 1] = type(line) == "table" and { "[Copilot] " .. line[1], line[2] } or { "[Copilot] " .. line } + lines[#lines + 1] = { "\n", "NONE" } + end + + local function flush_lines(last_line) + add_line(last_line) + + if c.startup_error then + add_line({ c.startup_error, "WarningMsg" }) + end + + vim.api.nvim_echo(lines, true, {}) + end + + if c.is_disabled() then + flush_lines("Offline") + return + end + + local client = c.get() + if not client then + flush_lines("Not Started") + return + end + + add_line("Online") + + coroutine.wrap(function() + local cserr, status = a.check_status(client) + if cserr then + flush_lines(cserr) + return + end + + if not status.user then + flush_lines("Not authenticated. Run ':Copilot auth'") + return + elseif status.status == "NoTelemetryConsent" then + flush_lines("Telemetry terms not accepted") + return + elseif status.status == "NotAuthorized" then + flush_lines("Not authorized") + return + end + + local should_attach, no_attach_reason = u.should_attach() + local is_attached = c.buf_is_attached() + if is_attached then + if not should_attach then + add_line("Enabled manually (" .. no_attach_reason .. ")") + else + add_line("Enabled for " .. vim.bo.filetype) + end + elseif not is_attached then + if should_attach then + add_line("Disabled manually for " .. vim.bo.filetype) + else + add_line("Disabled (" .. no_attach_reason .. ")") + end + end + + if string.lower(M.data.status) == "error" then + add_line(M.data.message) + end + + flush_lines() + end)() +end + +return M diff --git a/lua/copilot/suggestion/init.lua b/lua/copilot/suggestion/init.lua index 2e0bca96..22ffcfea 100644 --- a/lua/copilot/suggestion/init.lua +++ b/lua/copilot/suggestion/init.lua @@ -5,11 +5,7 @@ local hl_group = require("copilot.highlight").group local util = require("copilot.util") local logger = require("copilot.logger") -local _, has_nvim_0_10_x = pcall(function() - return vim.version().minor >= 10 -end) - -local mod = {} +local M = {} ---@alias copilot_suggestion_context { first?: integer, cycling?: integer, cycling_callbacks?: (fun(ctx: copilot_suggestion_context):nil)[], params?: table, suggestions?: copilot_get_completions_data_completion[], choice?: integer, shown_choices?: table } @@ -74,35 +70,35 @@ end local function set_keymap(keymap) if keymap.accept then - vim.keymap.set("i", keymap.accept, mod.accept, { + vim.keymap.set("i", keymap.accept, M.accept, { desc = "[copilot] accept suggestion", silent = true, }) end if keymap.accept_word then - vim.keymap.set("i", keymap.accept_word, mod.accept_word, { + vim.keymap.set("i", keymap.accept_word, M.accept_word, { desc = "[copilot] accept suggestion (word)", silent = true, }) end if keymap.accept_line then - vim.keymap.set("i", keymap.accept_line, mod.accept_line, { + vim.keymap.set("i", keymap.accept_line, M.accept_line, { desc = "[copilot] accept suggestion (line)", silent = true, }) end if keymap.next then - vim.keymap.set("i", keymap.next, mod.next, { + vim.keymap.set("i", keymap.next, M.next, { desc = "[copilot] next suggestion", silent = true, }) end if keymap.prev then - vim.keymap.set("i", keymap.prev, mod.prev, { + vim.keymap.set("i", keymap.prev, M.prev, { desc = "[copilot] prev suggestion", silent = true, }) @@ -110,8 +106,8 @@ local function set_keymap(keymap) if keymap.dismiss then vim.keymap.set("i", keymap.dismiss, function() - if mod.is_visible() then - mod.dismiss() + if M.is_visible() then + M.dismiss() return "" else return keymap.dismiss @@ -441,7 +437,7 @@ local function schedule(ctx) end) end -function mod.next() +function M.next() local ctx = get_ctx() logger.trace("suggestion next", ctx) @@ -457,7 +453,7 @@ function mod.next() end, ctx) end -function mod.prev() +function M.prev() local ctx = get_ctx() logger.trace("suggestion prev", ctx) @@ -474,7 +470,7 @@ function mod.prev() end ---@param modifier? (fun(suggestion: copilot_get_completions_data_completion): copilot_get_completions_data_completion) -function mod.accept(modifier) +function M.accept(modifier) local ctx = get_ctx() logger.trace("suggestion accept", ctx) @@ -531,15 +527,17 @@ function mod.accept(modifier) vim.lsp.util.apply_text_edits({ { range = range, newText = newText } }, bufnr, encoding) -- Put cursor at the end of current line. local cursor_keys = "" - if has_nvim_0_10_x then + + -- TODO: Move to util and check only once + if vim.fn.has("nvim-0.11") == 1 then cursor_keys = string.rep("", #vim.split(newText, "\n", { plain = true }) - 1) .. cursor_keys end vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(cursor_keys, true, false, true), "n", false) end)() end -function mod.accept_word() - mod.accept(function(suggestion) +function M.accept_word() + M.accept(function(suggestion) local range, text = suggestion.range, suggestion.text local cursor = vim.api.nvim_win_get_cursor(0) @@ -557,8 +555,8 @@ function mod.accept_word() end) end -function mod.accept_line() - mod.accept(function(suggestion) +function M.accept_line() + M.accept(function(suggestion) local text = suggestion.text local cursor = vim.api.nvim_win_get_cursor(0) @@ -574,19 +572,19 @@ function mod.accept_line() end) end -function mod.dismiss() +function M.dismiss() local ctx = get_ctx() reject() clear(ctx) update_preview(ctx) end -function mod.is_visible() +function M.is_visible() return not not vim.api.nvim_buf_get_extmark_by_id(0, copilot.ns_id, copilot.extmark_id, { details = false })[1] end -- toggles auto trigger for the current buffer -function mod.toggle_auto_trigger() +function M.toggle_auto_trigger() vim.b.copilot_suggestion_auto_trigger = not should_auto_trigger() end @@ -701,7 +699,7 @@ local function create_autocmds() }) end -function mod.setup() +function M.setup() local opts = config.suggestion if not opts.enabled then return @@ -722,7 +720,7 @@ function mod.setup() copilot.setup_done = true end -function mod.teardown() +function M.teardown() local opts = config.suggestion if not opts.enabled then return @@ -739,4 +737,4 @@ function mod.teardown() copilot.setup_done = false end -return mod +return M diff --git a/lua/copilot/suggestion/keymaps.lua b/lua/copilot/suggestion/keymaps.lua new file mode 100644 index 00000000..e69de29b diff --git a/lua/copilot/workspace/init.lua b/lua/copilot/workspace/init.lua index dd5173e3..3421eea1 100644 --- a/lua/copilot/workspace/init.lua +++ b/lua/copilot/workspace/init.lua @@ -1,11 +1,11 @@ local logger = require("copilot.logger") -local client = require("copilot.client") +local utils = require("copilot.workspace.utils") -local mod = {} +local M = {} ---@class workspace_folder ---@field uri string The URI of the workspace folder ---@field name string The name of the workspace folder -function mod.add(opts) +function M.add(opts) local folder = opts.args if not folder or folder == "" then logger.error("folder is required to add a workspace_folder") @@ -13,7 +13,7 @@ function mod.add(opts) end folder = vim.fn.fnamemodify(folder, ":p") - client.add_workspace_folder(folder) + utils.add_workspace_folder(folder) end -return mod +return M diff --git a/plugin/copilot.lua b/plugin/copilot.lua index d786f679..0832dd0e 100644 --- a/plugin/copilot.lua +++ b/plugin/copilot.lua @@ -28,6 +28,8 @@ vim.api.nvim_create_user_command("Copilot", function(opts) action_name = "open" elseif mod_name == "suggestion" then action_name = "toggle_auto_trigger" + elseif mod_name == "status" then + action_name = "status" end end From 200018604dcfc5a5c6dde4f7c2a7863d4138a823 Mon Sep 17 00:00:00 2001 From: Antoine Gaudreau Simard Date: Mon, 31 Mar 2025 14:05:25 -0400 Subject: [PATCH 4/7] feat: add validation of configuration --- lua/copilot/config/init.lua | 30 ++++++++++++++++++++++++---- lua/copilot/config/logger.lua | 28 +++++++++++++++++++++++++- lua/copilot/config/panel.lua | 27 +++++++++++++++++++++---- lua/copilot/config/root_dir.lua | 5 +++++ lua/copilot/config/server.lua | 16 +++++++++++++-- lua/copilot/config/should_attach.lua | 5 +++++ lua/copilot/config/suggestion.lua | 18 +++++++++++++++-- lua/copilot/workspace/utils.lua | 1 - 8 files changed, 116 insertions(+), 14 deletions(-) diff --git a/lua/copilot/config/init.lua b/lua/copilot/config/init.lua index dfafdcc7..272e880e 100644 --- a/lua/copilot/config/init.lua +++ b/lua/copilot/config/init.lua @@ -8,7 +8,7 @@ local logger = require("copilot.logger") ---@field filetypes table Filetypes to enable Copilot for ---@field auth_provider_url string|nil URL for the authentication provider ---@field workspace_folders string[] Workspace folders to enable Copilot for ----@field server_opts_overrides table Options to override for the server +---@field server_opts_overrides? table Options to override for the server ---@field copilot_model string|nil Model to use for Copilot, LSP server dictates the default ---@field root_dir RootDirFuncOrString Root directory for the project, defaults to the nearest .git directory ---@field should_attach ShouldAttachFunc Function to determine if Copilot should attach to the buffer @@ -32,6 +32,7 @@ local M = { copilot_node_command = "node", } +---@param user_configs CopilotConfig function M.merge_with_user_configs(user_configs) logger.trace("setting up configuration, opts", user_configs) @@ -45,11 +46,32 @@ function M.merge_with_user_configs(user_configs) M[k] = v end - if M.server.custom_server_filepath then - M.server.custom_server_filepath = vim.fs.normalize(M.server.custom_server_filepath) - end + M.validate(M) initialized = true end +---@param config CopilotConfig +function M.validate(config) + vim.validate("panel", config.panel, "table") + vim.validate("suggestion", config.suggestion, "table") + vim.validate("logger", config.logger, "table") + vim.validate("server", config.server, "table") + vim.validate("filetypes", config.filetypes, "table") + vim.validate("auth_provider_url", config.auth_provider_url, { "string", "nil" }) + vim.validate("workspace_folders", config.workspace_folders, "table") + vim.validate("server_opts_overrides", config.server_opts_overrides, "table", true) + vim.validate("copilot_model", config.copilot_model, { "string", "nil" }) + vim.validate("root_dir", config.root_dir, { "string", "function" }) + vim.validate("should_attach", config.should_attach, "function") + vim.validate("copilot_node_command", config.copilot_node_command, "string") + + require("copilot.config.panel").validate(config.panel) + require("copilot.config.suggestion").validate(config.suggestion) + require("copilot.config.logger").validate(config.logger) + require("copilot.config.server").validate(config.server) + require("copilot.config.root_dir").validate(config.root_dir) + require("copilot.config.should_attach").validate(config.should_attach) +end + return M diff --git a/lua/copilot/config/logger.lua b/lua/copilot/config/logger.lua index 4dff13a4..cadec489 100644 --- a/lua/copilot/config/logger.lua +++ b/lua/copilot/config/logger.lua @@ -1,4 +1,4 @@ ----@class LoggerConfig +---@class (exact) LoggerConfig ---@field file string Path to the log file ---@field file_log_level integer Log level for the log file, matches vim.log.levels ---@field print_log_level integer Log level for printing to the console, matches vim.log.levels @@ -18,4 +18,30 @@ local logger = { }, } +local function validate_log_level(level) + return type(level) == "number" + and ( + level == vim.log.levels.OFF + or level == vim.log.levels.ERROR + or level == vim.log.levels.WARN + or level == vim.log.levels.INFO + or level == vim.log.levels.DEBUG + or level == vim.log.levels.TRACE + ) +end + +---@param config LoggerConfig +function logger.validate(config) + vim.validate("file", config.file, "string") + config.file = vim.fs.normalize(config.file) + + vim.validate("file_log_level", config.file_log_level, validate_log_level, false, "any of the vim.log.levels") + vim.validate("print_log_level", config.print_log_level, validate_log_level, false, "any of the vim.log.levels") + vim.validate("trace_lsp", config.trace_lsp, function(level) + return level == "off" or level == "verbose" or level == "debug" + end, false, "off, verbose or debug") + vim.validate("trace_lsp_progress", config.trace_lsp_progress, "boolean") + vim.validate("log_lsp_messages", config.log_lsp_messages, "boolean") +end + return logger diff --git a/lua/copilot/config/panel.lua b/lua/copilot/config/panel.lua index 93a9550b..58a8eefd 100644 --- a/lua/copilot/config/panel.lua +++ b/lua/copilot/config/panel.lua @@ -1,17 +1,17 @@ ----@class PanelConfig +---@class (exact) PanelConfig ---@field enabled boolean Whether to enable the panel ---@field auto_refresh boolean Whether to automatically refresh the panel ---@field keymap PanelKeymapConfig Keymap for the panel ----@field layout config_panel_layout Layout of the panel +---@field layout PanelLayoutConfig Layout of the panel ----@class PanelKeymapConfig +---@class (exact) PanelKeymapConfig ---@field jump_prev string|false Keymap for jumping to the previous suggestion ---@field jump_next string|false Keymap for jumping to the next suggestion ---@field accept string|false Keymap for accepting the suggestion ---@field refresh string|false Keymap for refreshing the suggestion ---@field open string|false Keymap for opening the suggestion ----@class config_panel_layout +---@class (exact) PanelLayoutConfig ---@field position string<'left'|'right'|'top'|'bottom'> Position of the panel ---@field ratio number Ratio of the panel size, between 0 and 1 @@ -34,4 +34,23 @@ local panel = { }, } +---@param config PanelConfig +function panel.validate(config) + vim.validate("enabled", config.enabled, "boolean") + vim.validate("auto_refresh", config.auto_refresh, "boolean") + vim.validate("keymap", config.keymap, "table") + vim.validate("layout", config.layout, "table") + vim.validate("keymap.jump_prev", config.keymap.jump_prev, { "string", "boolean" }) + vim.validate("keymap.jump_next", config.keymap.jump_next, { "string", "boolean" }) + vim.validate("keymap.accept", config.keymap.accept, { "string", "boolean" }) + vim.validate("keymap.refresh", config.keymap.refresh, { "string", "boolean" }) + vim.validate("keymap.open", config.keymap.open, { "string", "boolean" }) + vim.validate("layout.position", config.layout.position, function(value) + return value == "left" or value == "right" or value == "top" or value == "bottom" + end, false, "left, right, top or bottom") + vim.validate("layout.ratio", config.layout.ratio, function(value) + return type(value) == "number" and value >= 0 and value <= 1 + end, false, "number between 0 and 1") +end + return panel diff --git a/lua/copilot/config/root_dir.lua b/lua/copilot/config/root_dir.lua index 99325f97..3e761ad4 100644 --- a/lua/copilot/config/root_dir.lua +++ b/lua/copilot/config/root_dir.lua @@ -7,4 +7,9 @@ local root_dir = { end, } +---@param config RootDirFuncOrString +function root_dir.validate(config) + vim.validate("root_dir", config, { "string", "function" }) +end + return root_dir diff --git a/lua/copilot/config/server.lua b/lua/copilot/config/server.lua index b5d28789..dc5f94d2 100644 --- a/lua/copilot/config/server.lua +++ b/lua/copilot/config/server.lua @@ -1,6 +1,6 @@ ----@class ServerConfig +---@class (exact) ServerConfig ---@field type string<'nodejs', 'binary'> Type of the server ----@field custom_server_filepath string|nil Path to the custom server file +---@field custom_server_filepath? string|nil Path to the custom server file local server = { ---@type ServerConfig @@ -10,4 +10,16 @@ local server = { }, } +---@param config ServerConfig +function server.validate(config) + vim.validate("type", config.type, function(server_type) + return type(server_type) == "string" and (server_type == "nodejs" or server_type == "binary") + end, false, "nodejs or binary") + vim.validate("custom_server_filepath", config.custom_server_filepath, { "string", "nil" }) + + if config.custom_server_filepath then + config.custom_server_filepath = vim.fs.normalize(config.custom_server_filepath) + end +end + return server diff --git a/lua/copilot/config/should_attach.lua b/lua/copilot/config/should_attach.lua index 3089b837..66849133 100644 --- a/lua/copilot/config/should_attach.lua +++ b/lua/copilot/config/should_attach.lua @@ -19,4 +19,9 @@ local should_attach = { end, } +---@param config ShouldAttachFunc +function should_attach.validate(config) + vim.validate("should_attach", config, "function") +end + return should_attach diff --git a/lua/copilot/config/suggestion.lua b/lua/copilot/config/suggestion.lua index 49543484..7c719ef3 100644 --- a/lua/copilot/config/suggestion.lua +++ b/lua/copilot/config/suggestion.lua @@ -1,11 +1,11 @@ ----@class SuggestionConfig +---@class (exact) SuggestionConfig ---@field enabled boolean Whether to enable the suggestion ---@field auto_trigger boolean Whether to trigger the suggestion automatically ---@field hide_during_completion boolean Whether to hide the suggestion during completion ---@field debounce integer Debounce time in milliseconds ---@field keymap SuggestionKeymapConfig Keymap for the suggestion ----@class SuggestionKeymapConfig +---@class (exact) SuggestionKeymapConfig ---@field accept string|false Keymap for accepting the suggestion ---@field accept_word string|false Keymap for accepting the word ---@field accept_line string|false Keymap for accepting the line @@ -31,4 +31,18 @@ local suggestion = { }, } +function suggestion.validate(config) + vim.validate("enabled", config.enabled, "boolean") + vim.validate("auto_trigger", config.auto_trigger, "boolean") + vim.validate("hide_during_completion", config.hide_during_completion, "boolean") + vim.validate("debounce", config.debounce, { "number", "nil" }) + vim.validate("keymap", config.keymap, "table") + vim.validate("keymap.accept", config.keymap.accept, { "string", "boolean" }) + vim.validate("keymap.accept_word", config.keymap.accept_word, { "string", "boolean" }) + vim.validate("keymap.accept_line", config.keymap.accept_line, { "string", "boolean" }) + vim.validate("keymap.next", config.keymap.next, { "string", "boolean" }) + vim.validate("keymap.prev", config.keymap.prev, { "string", "boolean" }) + vim.validate("keymap.dismiss", config.keymap.dismiss, { "string", "boolean" }) +end + return suggestion diff --git a/lua/copilot/workspace/utils.lua b/lua/copilot/workspace/utils.lua index 0d45e0b0..659d078c 100644 --- a/lua/copilot/workspace/utils.lua +++ b/lua/copilot/workspace/utils.lua @@ -15,7 +15,6 @@ function M.add_workspace_folder(folder_path) return false end - -- Normalize path folder_path = vim.fn.fnamemodify(folder_path, ":p") --- @type workspace_folder From 2cd99fbca30a9bbcd4ea67f885386c45be3b9e00 Mon Sep 17 00:00:00 2001 From: Antoine Gaudreau Simard Date: Fri, 4 Apr 2025 21:38:15 -0400 Subject: [PATCH 5/7] tests: initial round of tests using mini.test --- .luarc.json | 3 + Makefile | 13 + lua/copilot/client/config.lua | 24 +- lua/copilot/client/filetypes.lua | 30 +- lua/copilot/client/init.lua | 69 +- lua/copilot/client/utils.lua | 3 +- lua/copilot/command.lua | 35 +- lua/copilot/lsp/binary.lua | 25 +- lua/copilot/lsp/init.lua | 67 + lua/copilot/lsp/nodejs.lua | 17 + lua/copilot/status/init.lua | 27 +- lua/copilot/util.lua | 9 + plugin/copilot.lua | 1 - tests/logs/test_client.log | 327 ++ tests/logs/test_example.log | 5098 +++++++++++++++++ tests/logs/test_suggestion.log | 1025 ++++ ...tion.lua---suggestion()---suggestion-works | 23 + tests/scripts/minimal_init.lua | 12 + tests/scripts/minimal_manual_init.lua | 12 + tests/test_base_to_organize.lua | 52 + tests/test_client.lua | 76 + tests/test_panel.lua | 67 + tests/test_suggestion.lua | 54 + tests/utils.lua | 90 + 24 files changed, 7052 insertions(+), 107 deletions(-) create mode 100644 .luarc.json create mode 100644 Makefile create mode 100644 tests/logs/test_client.log create mode 100644 tests/logs/test_example.log create mode 100644 tests/logs/test_suggestion.log create mode 100644 tests/screenshots/tests-test_suggestion.lua---suggestion()---suggestion-works create mode 100644 tests/scripts/minimal_init.lua create mode 100644 tests/scripts/minimal_manual_init.lua create mode 100644 tests/test_base_to_organize.lua create mode 100644 tests/test_client.lua create mode 100644 tests/test_panel.lua create mode 100644 tests/test_suggestion.lua create mode 100644 tests/utils.lua diff --git a/.luarc.json b/.luarc.json new file mode 100644 index 00000000..155b29cc --- /dev/null +++ b/.luarc.json @@ -0,0 +1,3 @@ +{ + "_workspace.ignoreDir": ["deps"] +} diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..f7e12593 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +# Run all test files +# test: deps/mini.nvim +test: + nvim --headless --noplugin -u ./scripts/minimal_init.lua -c "lua MiniTest.run()" + +# Run test from file at `$FILE` environment variable +test_file: deps/mini.nvim + nvim --headless --noplugin -u ./scripts/minimal_init.lua -c "lua MiniTest.run_file('$(FILE)')" + +# Download 'mini.nvim' to use its 'mini.test' testing module +# deps/mini.nvim: +# @mkdir deps +# git clone --filter=blob:none https://github.com/echasnovski/mini.nvim $@ diff --git a/lua/copilot/client/config.lua b/lua/copilot/client/config.lua index a27bb4c4..7f8ec6b2 100644 --- a/lua/copilot/client/config.lua +++ b/lua/copilot/client/config.lua @@ -16,25 +16,7 @@ function M.prepare_client_config(overrides, client) client.startup_error = nil - local server_path = nil - local cmd = nil - - if config.server.custom_server_filepath and vim.fn.filereadable(config.server.custom_server_filepath) then - server_path = config.server.custom_server_filepath - end - - if config.server.type == "nodejs" then - cmd = { - lsp.nodejs.node_command, - server_path or lsp.nodejs.get_server_path(), - "--stdio", - } - elseif config.server.type == "binary" then - cmd = { - server_path or lsp.binary.get_server_path(), - "--stdio", - } - end + local cmd = lsp.get_execute_command() if not cmd then logger.error("copilot server type not supported") @@ -84,7 +66,7 @@ function M.prepare_client_config(overrides, client) } if proxy_uri then - vim.tbl_extend("force", settings, { + settings = vim.tbl_extend("force", settings, { http = { ---@type copilot_settings_http proxy = proxy_uri, proxyStrictSSL = vim.g.copilot_proxy_strict_ssl or false, @@ -94,7 +76,7 @@ function M.prepare_client_config(overrides, client) end if provider_url then - vim.tbl_extend("force", settings, { + settings = vim.tbl_extend("force", settings, { ["github-enterprise"] = { ---@type copilot_settings_github-enterprise uri = provider_url, }, diff --git a/lua/copilot/client/filetypes.lua b/lua/copilot/client/filetypes.lua index ebe68dbf..54adb717 100644 --- a/lua/copilot/client/filetypes.lua +++ b/lua/copilot/client/filetypes.lua @@ -1,4 +1,16 @@ -local M = {} +local M = { + internal_filetypes = { + yaml = false, + markdown = false, + help = false, + gitcommit = false, + gitrebase = false, + hgcommit = false, + svn = false, + cvs = false, + ["."] = false, + }, +} local language_normalization_map = { bash = "shellscript", @@ -27,18 +39,6 @@ function M.language_for_file_type(filetype) return language_normalization_map[ft] or ft end -local internal_filetypes = { - yaml = false, - markdown = false, - help = false, - gitcommit = false, - gitrebase = false, - hgcommit = false, - svn = false, - cvs = false, - ["."] = false, -} - ---@param filetype_enabled boolean|fun():boolean local function resolve_filetype_enabled(filetype_enabled) if type(filetype_enabled) == "function" then @@ -69,8 +69,8 @@ function M.is_ft_disabled(ft, filetypes) string.format("'filetype' %s rejected by config filetypes[%s]", ft, "*") end - if internal_filetypes[short_ft] ~= nil then - return not internal_filetypes[short_ft], + if M.internal_filetypes[short_ft] ~= nil then + return not M.internal_filetypes[short_ft], string.format("'filetype' %s rejected by internal_filetypes[%s]", ft, short_ft) end diff --git a/lua/copilot/client/init.lua b/lua/copilot/client/init.lua index 478f80df..35753120 100644 --- a/lua/copilot/client/init.lua +++ b/lua/copilot/client/init.lua @@ -38,7 +38,8 @@ end ---@param force? boolean function M.buf_attach(force) - if lsp.binary.initialization_failed then + if lsp.initialization_failed() then + logger.error("copilot-language-server failed to initialize") M.startup_error = "initialization of copilot-language-server failed" return end @@ -48,10 +49,7 @@ function M.buf_attach(force) return end - local bufnr = vim.api.nvim_get_current_buf() - local bufname = vim.api.nvim_buf_get_name(bufnr) - - if not (force or (config.should_attach(bufnr, bufname) and util.should_attach())) then + if not (force or util.should_attach()) then logger.debug("not attaching to buffer based on force and should_attach criteria") return end @@ -64,6 +62,7 @@ function M.buf_attach(force) -- In case it has changed, we update it M.config.root_dir = utils.get_root_dir(config.root_dir) + logger.trace("attaching to buffer") local ok, client_id_or_err = pcall(vim.lsp.start, M.config) if not ok then logger.error(string.format("failed to start LSP client: %s", client_id_or_err)) @@ -75,6 +74,7 @@ function M.buf_attach(force) else logger.error("LSP client failed to start (no client ID returned)") end + logger.trace("buffer attached") end function M.buf_detach() @@ -83,7 +83,7 @@ function M.buf_detach() end end ----@return nil|vim.lsp.Client +---@return vim.lsp.Client|nil function M.get() return vim.lsp.get_client_by_id(M.id) end @@ -95,11 +95,11 @@ end ---@param callback fun(client:table):nil function M.use_client(callback) if is_disabled then - logger.warn("copilot is offline") + logger.notify("copilot is offline") return end - local client = M.get() --[[@as table]] + local client = M.get() if not client then if not M.config then @@ -124,36 +124,37 @@ function M.use_client(callback) return end - local timer, err, _ = vim.uv.new_timer() - - if not timer then - logger.error(string.format("error creating timer: %s", err)) - return - end - - timer:start( - 0, - 100, - vim.schedule_wrap(function() - if client.initialized and not timer:is_closing() then - timer:stop() - timer:close() - callback(client) - end - end) - ) + logger.error("client is not initialized yet") + -- Following code is commented out for now because: + -- 1) I am hoping it is not needed anymore and + -- 2) It causes issues with testing >_< + -- + -- local timer, err, _ = vim.uv.new_timer() + -- + -- if not timer then + -- logger.error(string.format("error creating timer: %s", err)) + -- return + -- end + -- + -- timer:start( + -- 0, + -- 100, + -- vim.schedule_wrap(function() + -- if client.initialized and not timer:is_closing() then + -- timer:stop() + -- timer:close() + -- callback(client) + -- else + -- logger.error("client not initialized yet") + -- end + -- end) + -- ) end function M.setup() + logger.trace("setting up client") local node_command = config.copilot_node_command - - --TODO: merge the two types into an indirection - if config.server.type == "nodejs" then - lsp.nodejs.setup(node_command, config.server.custom_server_filepath) - elseif config.server.type == "binary" then - lsp.binary.setup(config.server.custom_server_filepath) - end - + lsp.setup(config.server, node_command) M.config = require("copilot.client.config").prepare_client_config(config.server_opts_overrides, M) if not M.config then diff --git a/lua/copilot/client/utils.lua b/lua/copilot/client/utils.lua index 45a774fe..b2398c0b 100644 --- a/lua/copilot/client/utils.lua +++ b/lua/copilot/client/utils.lua @@ -1,5 +1,6 @@ local config = require("copilot.config") local logger = require("copilot.logger") +local client_ft = require("copilot.client.filetypes") local M = {} ---@param config_root_dir RootDirFuncOrString @@ -25,7 +26,7 @@ function M.get_workspace_configurations() local filetypes = vim.deepcopy(config.filetypes) --[[@as table]] if filetypes["*"] == nil then - filetypes = vim.tbl_deep_extend("keep", filetypes, require("copilot.client.filetypes").internal_filetypes) + filetypes = vim.tbl_deep_extend("keep", filetypes, client_ft.internal_filetypes) end local copilot_model = config and config.copilot_model ~= "" and config.copilot_model or "" diff --git a/lua/copilot/command.lua b/lua/copilot/command.lua index 0085e798..2d27ff5c 100644 --- a/lua/copilot/command.lua +++ b/lua/copilot/command.lua @@ -1,53 +1,38 @@ -local a = require("copilot.api") local c = require("copilot.client") local u = require("copilot.util") +local logger = require("copilot.logger") +local lsp = require("copilot.lsp") local M = {} function M.version() local info = u.get_editor_info() - ---@type (string|table)[] + ---@type string local lines = { info.editorInfo.name .. " " .. info.editorInfo.version, - "copilot.vim" .. " " .. info.editorPluginInfo.version, + "copilot language server" .. " " .. info.editorPluginInfo.version, "copilot.lua" .. " " .. u.get_copilot_lua_version(), } local client = c.get() coroutine.wrap(function() - -- TODO: this is now in lsp/* - local copilot_server_info = u.get_copilot_server_info() - if client then - local _, data = a.get_version(client) - lines[#lines + 1] = copilot_server_info.path .. "/" .. copilot_server_info().filename .. " " .. data.version - else - lines[#lines + 1] = copilot_server_info.path .. "/" .. copilot_server_info().filename .. " " .. "not running" - end - - local chunks = {} - for _, line in ipairs(lines) do - chunks[#chunks + 1] = type(line) == "table" and line or { line } - chunks[#chunks + 1] = { "\n", "NONE" } - end - - vim.api.nvim_echo(chunks, true, {}) + local server_info = lsp.get_server_info(client) + logger.notify(lines .. "\n" .. server_info) end)() end ---@param opts? { force?: boolean } function M.attach(opts) + logger.trace("attaching to buffer") opts = opts or {} if not opts.force then local should_attach, no_attach_reason = u.should_attach() - -- TODO: add other should_attach method here + if not should_attach then - vim.api.nvim_echo({ - { "[Copilot] " .. no_attach_reason .. "\n" }, - { "[Copilot] to force attach, run ':Copilot! attach'" }, - }, true, {}) + logger.notify(no_attach_reason .. "\nto force attach, run ':Copilot! attach'") return end @@ -76,12 +61,14 @@ function M.toggle(opts) end function M.enable() + logger.trace("enabling Copilot") c.setup() require("copilot.panel").setup() require("copilot.suggestion").setup() end function M.disable() + logger.trace("disabling Copilot") c.teardown() require("copilot.panel").teardown() require("copilot.suggestion").teardown() diff --git a/lua/copilot/lsp/binary.lua b/lua/copilot/lsp/binary.lua index de745d9b..90671d91 100644 --- a/lua/copilot/lsp/binary.lua +++ b/lua/copilot/lsp/binary.lua @@ -180,10 +180,9 @@ local function set_permissions(filename) return true end --- TODO: when this fails, it will cause a couple more errors before crashing -- let's hope the naming convention does not change!!! ---@return boolean -function M.ensure_client_is_downloaded() +function M.init() if M.initialized then return true elseif M.initialization_failed then @@ -268,6 +267,26 @@ local function is_musl() return string.sub(ldd_output, 1, 4) == "musl" end +---@param client vim.lsp.Client|nil +---@return string +function M.get_server_info(client) + local copilot_server_info = M.get_copilot_server_info() + + if client then + return copilot_server_info.path .. "/" .. copilot_server_info().filename + else + return copilot_server_info.path .. "/" .. copilot_server_info().filename .. " " .. "not running" + end +end + +---@return table +function M.get_execute_command() + return { + M.server_path or M.get_server_path(), + "--stdio", + } +end + ---@return copilot_server_info function M.get_copilot_server_info() if M.copilot_server_info then @@ -345,8 +364,6 @@ function M.setup(custom_server_path) M.initialized = true end - - M.ensure_client_is_downloaded() end return M diff --git a/lua/copilot/lsp/init.lua b/lua/copilot/lsp/init.lua index 93af098e..b2da9079 100644 --- a/lua/copilot/lsp/init.lua +++ b/lua/copilot/lsp/init.lua @@ -1,6 +1,73 @@ +local logger = require("copilot.logger") + local M = { binary = require("copilot/lsp/binary"), nodejs = require("copilot/lsp/nodejs"), + ---@type ServerConfig + config = nil, } +---@return boolean +function M.initialization_failed() + if M.config.type == "nodejs" then + return M.nodejs.initialization_failed + elseif M.config.type == "binary" then + return M.binary.initialization_failed + end + + return true +end + +---@return boolean +function M.init() + if M.config.type == "nodejs" then + return M.nodejs.init() + elseif M.config.type == "binary" then + return M.binary.init() + end + + return false +end + +---@param client vim.lsp.Client|nil +---@return string +function M.get_server_info(client) + if M.config.type == "nodejs" then + return M.nodejs.get_server_info(client) + elseif M.config.type == "binary" then + return M.binary.get_server_info(client) + end + + return "" +end + +---@return table +function M.get_execute_command() + if M.config.type == "nodejs" then + return M.nodejs.get_execute_command() + elseif M.config.type == "binary" then + return M.binary.get_execute_command() + end + + return {} +end + +---@param server_config ServerConfig +---@param copilot_node_command string +function M.setup(server_config, copilot_node_command) + if not server_config then + logger.error("server_config is required") + end + + if server_config.type == "nodejs" then + M.nodejs.setup(copilot_node_command, server_config.custom_server_filepath) + elseif server_config.type == "binary" then + M.binary.setup(server_config.custom_server_filepath) + else + logger.error("invalid server_config.type") + end + + M.config = server_config +end + return M diff --git a/lua/copilot/lsp/nodejs.lua b/lua/copilot/lsp/nodejs.lua index 74e0fbd8..b90d6920 100644 --- a/lua/copilot/lsp/nodejs.lua +++ b/lua/copilot/lsp/nodejs.lua @@ -6,6 +6,7 @@ local M = { node_command = nil, ---@type string server_path = nil, + initialization_failed = false, } ---@return string node_version @@ -38,6 +39,12 @@ function M.get_node_version() return M.node_version, M.node_version_error end +---@param _ vim.lsp.Client|nil +---@return string +function M.get_server_info(_) + return string.format("Node.js %s\nLanguage server: %s\n", M.get_node_version(), M.server_path) +end + ---@return boolean function M.validate_node_version() local _, node_version_error = M.get_node_version() @@ -68,6 +75,7 @@ function M.init_agent_path(server_path) if not agent_path or vim.fn.filereadable(agent_path) == 0 then logger.error(string.format("could not find server (bad install?) : %s", tostring(agent_path))) + M.initialization_failed = true return false end @@ -85,6 +93,15 @@ function M.get_server_path() return M.server_path end +---@return table +function M.get_execute_command() + return { + M.node_command, + M.server_path or M.get_server_path(), + "--stdio", + } +end + ---@param node_command? string ---@param custom_server_path? string ---@return boolean diff --git a/lua/copilot/status/init.lua b/lua/copilot/status/init.lua index 99b0bd90..0ee7e643 100644 --- a/lua/copilot/status/init.lua +++ b/lua/copilot/status/init.lua @@ -1,6 +1,7 @@ local u = require("copilot.util") local c = require("copilot.client") local a = require("copilot.api") +local logger = require("copilot.logger") ---@alias copilot_status_notification_data { status: ''|'Normal'|'InProgress'|'Warning', message: string } local M = { @@ -39,25 +40,31 @@ function M.unregister_status_notification_handler(handler) end function M.status() - local lines = {} + logger.trace("Status called") + local lines = "Status:" + ---@param line string|nil local function add_line(line) if not line then return end - lines[#lines + 1] = type(line) == "table" and { "[Copilot] " .. line[1], line[2] } or { "[Copilot] " .. line } - lines[#lines + 1] = { "\n", "NONE" } + if lines ~= "" then + lines = lines .. "\n" .. line + else + lines = line + end end + ---@param last_line string|nil local function flush_lines(last_line) add_line(last_line) if c.startup_error then - add_line({ c.startup_error, "WarningMsg" }) + add_line(c.startup_error) end - vim.api.nvim_echo(lines, true, {}) + logger.notify(lines) end if c.is_disabled() then @@ -96,12 +103,18 @@ function M.status() if is_attached then if not should_attach then add_line("Enabled manually (" .. no_attach_reason .. ")") - else + elseif vim.bo.filetype and vim.bo.filetype ~= "" then add_line("Enabled for " .. vim.bo.filetype) + else + add_line("Enabled") end elseif not is_attached then if should_attach then - add_line("Disabled manually for " .. vim.bo.filetype) + if vim.bo.filetype and vim.bo.filetype ~= "" then + add_line("Disabled manually for " .. vim.bo.filetype) + else + add_line("Disabled manually") + end else add_line("Disabled (" .. no_attach_reason .. ")") end diff --git a/lua/copilot/util.lua b/lua/copilot/util.lua index 8a5a5f8e..3f2d8ff3 100644 --- a/lua/copilot/util.lua +++ b/lua/copilot/util.lua @@ -20,6 +20,7 @@ function M.get_editor_info() end local copilot_lua_version = nil + function M.get_copilot_lua_version() if not copilot_lua_version then local plugin_version_ok, plugin_version = pcall(function() @@ -41,6 +42,14 @@ function M.should_attach() return not ft_disabled, ft_disabled_reason end + local bufnr = vim.api.nvim_get_current_buf() + local bufname = vim.api.nvim_buf_get_name(bufnr) + local conf_attach = config.should_attach(bufnr, bufname) + + if not conf_attach then + return false, "copilot is disabled" + end + return true end diff --git a/plugin/copilot.lua b/plugin/copilot.lua index 0832dd0e..4a87d4bd 100644 --- a/plugin/copilot.lua +++ b/plugin/copilot.lua @@ -34,7 +34,6 @@ vim.api.nvim_create_user_command("Copilot", function(opts) end if not mod[action_name] then - print("[Copilot] Unknown params: " .. opts.args) return end diff --git a/tests/logs/test_client.log b/tests/logs/test_client.log new file mode 100644 index 00000000..5465de8e --- /dev/null +++ b/tests/logs/test_client.log @@ -0,0 +1,327 @@ +2025-04-04 21:27:05.082 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_client.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 21:27:05.083 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 21:27:05.085 [3] [TRACE]: attaching to buffer +2025-04-04 21:27:05.095 [4] [TRACE]: buffer attached +2025-04-04 21:27:05.333 [5] [TRACE]: api notify: +"workspace/didChangeConfiguration" +{ + settings = { + disabledLanguages = { { + languageId = "." + }, { + languageId = "cvs" + }, { + languageId = "gitcommit" + }, { + languageId = "gitrebase" + }, { + languageId = "help" + }, { + languageId = "hgcommit" + }, { + languageId = "markdown" + }, { + languageId = "svn" + }, { + languageId = "yaml" + } }, + enableAutoCompletions = true, + github = { + copilot = { + selectedCompletionModel = "" + } + } + } +} +2025-04-04 21:27:05.334 [7] [TRACE]: api notify: +"$/setTrace" +{ + value = "off" +} +2025-04-04 21:27:05.334 [6] [TRACE]: workspace configuration +{ + settings = { + disabledLanguages = { { + languageId = "." + }, { + languageId = "cvs" + }, { + languageId = "gitcommit" + }, { + languageId = "gitrebase" + }, { + languageId = "help" + }, { + languageId = "hgcommit" + }, { + languageId = "markdown" + }, { + languageId = "svn" + }, { + languageId = "yaml" + } }, + enableAutoCompletions = true, + github = { + copilot = { + selectedCompletionModel = "" + } + } + } +} +2025-04-04 21:27:05.590 [8] [TRACE]: Status called +2025-04-04 21:27:05.590 [9] [TRACE]: api request: +"checkStatus" +{} +2025-04-04 21:27:06.956 [10] [INFO]: Status: +Online +Enabled +2025-04-04 21:27:06.098 [12] [TRACE]: suggestion context +2025-04-04 21:27:06.098 [13] [TRACE]: suggestion new context +{} +2025-04-04 21:27:06.100 [15] [TRACE]: suggestion new context +{} +2025-04-04 21:27:06.100 [14] [TRACE]: suggestion context diff --git a/tests/logs/test_example.log b/tests/logs/test_example.log new file mode 100644 index 00000000..c0e5de3c --- /dev/null +++ b/tests/logs/test_example.log @@ -0,0 +1,5098 @@ +2025-04-04 20:13:31.086 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:13:31.087 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:13:31.088 [3] [TRACE]: attaching to buffer +2025-04-04 20:13:31.089 [4] [ERROR]: LSP client failed to start (no client ID returned) +2025-04-04 20:13:31.089 [6] [TRACE]: buffer attached +2025-04-04 20:13:33.100 [7] [TRACE]: suggestion context +2025-04-04 20:13:33.100 [8] [TRACE]: suggestion new context +{} +2025-04-04 20:13:33.100 [9] [TRACE]: suggestion context +2025-04-04 20:13:33.100 [10] [TRACE]: suggestion new context +{} +2025-04-04 20:13:33.085 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:13:33.086 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:13:33.087 [3] [TRACE]: attaching to buffer +2025-04-04 20:13:33.088 [4] [ERROR]: LSP client failed to start (no client ID returned) +2025-04-04 20:13:33.088 [6] [TRACE]: buffer attached +2025-04-04 20:13:34.110 [7] [ERROR]: error starting LSP client: nil +2025-04-04 20:13:34.118 [9] [TRACE]: suggestion context +2025-04-04 20:13:34.118 [10] [TRACE]: suggestion new context +{} +2025-04-04 20:13:34.118 [11] [TRACE]: suggestion context +2025-04-04 20:13:34.118 [12] [TRACE]: suggestion new context +{} +2025-04-04 20:19:57.044 [2] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:19:57.045 [3] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:19:57.048 [5] [ERROR]: failed to start LSP client: ...m Files\Neovim\share\nvim\runtime/lua/vim/lsp/client.lua:547: attempt to call field 'request' (a nil value) +2025-04-04 20:19:57.046 [4] [TRACE]: attaching to buffer +2025-04-04 20:19:58.066 [7] [TRACE]: suggestion context +2025-04-04 20:19:58.066 [8] [TRACE]: suggestion new context +{} +2025-04-04 20:19:58.066 [9] [TRACE]: suggestion context +2025-04-04 20:19:58.066 [10] [TRACE]: suggestion new context +{} +2025-04-04 20:19:59.047 [2] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:19:59.047 [3] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:19:59.048 [4] [TRACE]: attaching to buffer +2025-04-04 20:19:59.050 [5] [ERROR]: failed to start LSP client: ...m Files\Neovim\share\nvim\runtime/lua/vim/lsp/client.lua:547: attempt to call field 'request' (a nil value) +2025-04-04 20:20:00.068 [7] [ERROR]: client is not initialized yet +2025-04-04 20:20:00.068 [9] [ERROR]: client not initialized yet +2025-04-04 20:20:00.070 [11] [TRACE]: suggestion context +2025-04-04 20:20:00.070 [12] [TRACE]: suggestion new context +{} +2025-04-04 20:20:00.070 [13] [TRACE]: suggestion context +2025-04-04 20:20:00.070 [14] [TRACE]: suggestion new context +{} +2025-04-04 20:21:57.091 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:21:57.092 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:21:57.093 [3] [TRACE]: attaching to buffer +2025-04-04 20:21:57.095 [4] [ERROR]: failed to start LSP client: ...m Files\Neovim\share\nvim\runtime/lua/vim/lsp/client.lua:547: attempt to call field 'request' (a nil value) +2025-04-04 20:21:58.104 [6] [TRACE]: suggestion context +2025-04-04 20:21:58.104 [9] [TRACE]: suggestion new context +{} +2025-04-04 20:21:58.104 [8] [TRACE]: suggestion context +2025-04-04 20:21:58.104 [7] [TRACE]: suggestion new context +{} +2025-04-04 20:21:58.084 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:21:58.085 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:21:58.086 [3] [TRACE]: attaching to buffer +2025-04-04 20:21:58.088 [4] [ERROR]: failed to start LSP client: ...m Files\Neovim\share\nvim\runtime/lua/vim/lsp/client.lua:547: attempt to call field 'request' (a nil value) +2025-04-04 20:21:59.102 [6] [ERROR]: client is not initialized yet +2025-04-04 20:21:59.102 [8] [ERROR]: client not initialized yet +2025-04-04 20:21:59.106 [10] [TRACE]: suggestion context +2025-04-04 20:21:59.106 [11] [TRACE]: suggestion new context +{} +2025-04-04 20:21:59.106 [13] [TRACE]: suggestion new context +{} +2025-04-04 20:21:59.106 [12] [TRACE]: suggestion context +2025-04-04 20:22:49.085 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:22:49.086 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:22:49.087 [3] [TRACE]: attaching to buffer +2025-04-04 20:22:49.089 [4] [ERROR]: failed to start LSP client: ...m Files\Neovim\share\nvim\runtime/lua/vim/lsp/client.lua:547: attempt to call field 'request' (a nil value) +2025-04-04 20:22:50.114 [6] [TRACE]: suggestion context +2025-04-04 20:22:50.114 [7] [TRACE]: suggestion new context +{} +2025-04-04 20:22:50.114 [8] [TRACE]: suggestion context +2025-04-04 20:22:50.114 [9] [TRACE]: suggestion new context +{} +2025-04-04 20:22:50.081 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:22:50.082 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:22:50.083 [3] [TRACE]: attaching to buffer +2025-04-04 20:22:50.085 [4] [ERROR]: failed to start LSP client: ...m Files\Neovim\share\nvim\runtime/lua/vim/lsp/client.lua:547: attempt to call field 'request' (a nil value) +2025-04-04 20:22:51.098 [6] [ERROR]: client not initialized yet +2025-04-04 20:22:51.098 [8] [TRACE]: suggestion context +2025-04-04 20:22:51.098 [9] [TRACE]: suggestion new context +{} +2025-04-04 20:22:51.100 [11] [TRACE]: suggestion new context +{} +2025-04-04 20:22:51.098 [10] [TRACE]: suggestion context +2025-04-04 20:24:14.083 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:24:14.083 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:24:14.085 [3] [TRACE]: attaching to buffer +2025-04-04 20:24:14.087 [4] [ERROR]: failed to start LSP client: ...m Files\Neovim\share\nvim\runtime/lua/vim/lsp/client.lua:547: attempt to call field 'request' (a nil value) +2025-04-04 20:24:15.114 [6] [TRACE]: suggestion context +2025-04-04 20:24:15.114 [7] [TRACE]: suggestion new context +{} +2025-04-04 20:24:15.114 [8] [TRACE]: suggestion context +2025-04-04 20:24:15.114 [9] [TRACE]: suggestion new context +{} +2025-04-04 20:24:15.081 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:24:15.082 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = , + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:24:15.085 [4] [ERROR]: failed to start LSP client: ...m Files\Neovim\share\nvim\runtime/lua/vim/lsp/client.lua:547: attempt to call field 'request' (a nil value) +2025-04-04 20:24:15.083 [3] [TRACE]: attaching to buffer +2025-04-04 20:24:16.092 [6] [ERROR]: client is not initialized yet +2025-04-04 20:24:16.094 [8] [TRACE]: suggestion context +2025-04-04 20:24:16.094 [9] [TRACE]: suggestion new context +{} +2025-04-04 20:24:16.094 [10] [TRACE]: suggestion context +2025-04-04 20:24:16.094 [11] [TRACE]: suggestion new context +{} +2025-04-04 20:28:41.085 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:28:41.086 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:28:41.088 [4] [TRACE]: config +{ "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" } +2025-04-04 20:28:41.097 [5] [TRACE]: buffer attached +2025-04-04 20:28:41.088 [3] [TRACE]: attaching to buffer +2025-04-04 20:28:41.102 [6] [TRACE]: suggestion context +2025-04-04 20:28:41.102 [7] [TRACE]: suggestion new context +{} +2025-04-04 20:28:41.104 [8] [TRACE]: suggestion context +2025-04-04 20:28:41.104 [9] [TRACE]: suggestion new context +{} +2025-04-04 20:28:41.083 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:28:41.085 [3] [TRACE]: attaching to buffer +2025-04-04 20:28:41.084 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:28:41.095 [5] [TRACE]: buffer attached +2025-04-04 20:28:41.085 [4] [TRACE]: config +{ "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" } +2025-04-04 20:28:41.098 [6] [ERROR]: client is not initialized yet +2025-04-04 20:28:41.100 [8] [TRACE]: suggestion context +2025-04-04 20:28:41.101 [10] [TRACE]: suggestion context +2025-04-04 20:28:41.100 [9] [TRACE]: suggestion new context +{} +2025-04-04 20:28:41.101 [11] [TRACE]: suggestion new context +{} +2025-04-04 20:30:25.082 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:30:25.083 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:30:25.084 [3] [TRACE]: attaching to buffer +2025-04-04 20:30:25.095 [4] [TRACE]: buffer attached +2025-04-04 20:30:25.099 [5] [TRACE]: suggestion context +2025-04-04 20:30:25.099 [6] [TRACE]: suggestion new context +{} +2025-04-04 20:30:25.100 [7] [TRACE]: suggestion context +2025-04-04 20:30:25.100 [8] [TRACE]: suggestion new context +{} +2025-04-04 20:30:25.082 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 20:30:25.083 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 20:30:25.084 [3] [TRACE]: attaching to buffer +2025-04-04 20:30:25.094 [4] [TRACE]: buffer attached +2025-04-04 20:30:25.097 [5] [ERROR]: client is not initialized yet +2025-04-04 20:30:25.099 [7] [TRACE]: suggestion context +2025-04-04 20:30:25.099 [8] [TRACE]: suggestion new context +{} +2025-04-04 20:30:25.101 [9] [TRACE]: suggestion context +2025-04-04 20:30:25.101 [10] [TRACE]: suggestion new context +{} +2025-04-04 21:23:28.083 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 21:23:28.084 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 21:23:28.095 [4] [TRACE]: buffer attached +2025-04-04 21:23:28.085 [3] [TRACE]: attaching to buffer +2025-04-04 21:23:28.097 [6] [TRACE]: suggestion new context +{} +2025-04-04 21:23:28.097 [5] [TRACE]: suggestion context +2025-04-04 21:23:28.098 [7] [TRACE]: suggestion context +2025-04-04 21:23:28.098 [8] [TRACE]: suggestion new context +{} +2025-04-04 21:23:29.085 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 21:23:29.085 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 21:23:29.097 [4] [TRACE]: buffer attached +2025-04-04 21:23:29.087 [3] [TRACE]: attaching to buffer +2025-04-04 21:23:29.097 [5] [ERROR]: client is not initialized yet +2025-04-04 21:23:29.098 [7] [TRACE]: suggestion context +2025-04-04 21:23:29.098 [8] [TRACE]: suggestion new context +{} +2025-04-04 21:23:29.100 [10] [TRACE]: suggestion new context +{} +2025-04-04 21:23:29.100 [9] [TRACE]: suggestion context +2025-04-04 21:26:16.081 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 21:26:16.082 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 21:26:16.093 [4] [TRACE]: buffer attached +2025-04-04 21:26:16.083 [3] [TRACE]: attaching to buffer +2025-04-04 21:26:16.096 [5] [TRACE]: suggestion context +2025-04-04 21:26:16.096 [6] [TRACE]: suggestion new context +{} +2025-04-04 21:26:16.097 [7] [TRACE]: suggestion context +2025-04-04 21:26:16.097 [8] [TRACE]: suggestion new context +{} +2025-04-04 21:26:16.082 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 21:26:16.083 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 21:26:16.094 [4] [TRACE]: buffer attached +2025-04-04 21:26:16.084 [3] [TRACE]: attaching to buffer +2025-04-04 21:26:16.097 [5] [ERROR]: client is not initialized yet +2025-04-04 21:26:16.098 [8] [TRACE]: suggestion new context +{} +2025-04-04 21:26:16.098 [7] [TRACE]: suggestion context +2025-04-04 21:26:16.099 [9] [TRACE]: suggestion context +2025-04-04 21:26:16.099 [10] [TRACE]: suggestion new context +{} +2025-04-04 21:27:04.083 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 21:27:04.084 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 21:27:04.095 [4] [TRACE]: buffer attached +2025-04-04 21:27:04.086 [3] [TRACE]: attaching to buffer +2025-04-04 21:27:04.100 [5] [TRACE]: suggestion context +2025-04-04 21:27:04.100 [6] [TRACE]: suggestion new context +{} +2025-04-04 21:27:04.101 [7] [TRACE]: suggestion context +2025-04-04 21:27:04.101 [8] [TRACE]: suggestion new context +{} +2025-04-04 21:27:05.084 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = {}, + logger = { + file = "tests/logs/test_example.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = false, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 21:27:05.085 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 21:27:05.086 [3] [TRACE]: attaching to buffer +2025-04-04 21:27:05.097 [4] [TRACE]: buffer attached +2025-04-04 21:27:05.099 [5] [ERROR]: client is not initialized yet +2025-04-04 21:27:05.101 [7] [TRACE]: suggestion context +2025-04-04 21:27:05.101 [8] [TRACE]: suggestion new context +{} +2025-04-04 21:27:05.103 [9] [TRACE]: suggestion context +2025-04-04 21:27:05.103 [10] [TRACE]: suggestion new context +{} diff --git a/tests/logs/test_suggestion.log b/tests/logs/test_suggestion.log new file mode 100644 index 00000000..a0dc918c --- /dev/null +++ b/tests/logs/test_suggestion.log @@ -0,0 +1,1025 @@ +2025-04-04 21:29:30.083 [1] [DEBUG]: active plugin config: +{ + copilot_node_command = "node", + filetypes = { + ["*"] = true + }, + logger = { + file = "tests/logs/test_suggestion.log", + file_log_level = 0, + log_lsp_messages = false, + print_log_level = 3, + trace_lsp = "off", + trace_lsp_progress = false + }, + merge_with_user_configs = , + panel = { + auto_refresh = false, + enabled = true, + keymap = { + accept = "", + jump_next = "]]", + jump_prev = "[[", + open = "", + refresh = "gr" + }, + layout = { + position = "bottom", + ratio = 0.4 + } + }, + root_dir = , + server = { + type = "nodejs" + }, + server_opts_overrides = {}, + should_attach = , + suggestion = { + auto_trigger = true, + debounce = 15, + enabled = true, + hide_during_completion = true, + keymap = { + accept = "", + accept_line = false, + accept_word = false, + dismiss = "", + next = "", + prev = "" + } + }, + validate = , + workspace_folders = {} +} +2025-04-04 21:29:30.084 [2] [DEBUG]: active LSP config (may change runtime): +{ + capabilities = { + general = { + positionEncodings = { "utf-8", "utf-16", "utf-32" } + }, + textDocument = { + callHierarchy = { + dynamicRegistration = false + }, + codeAction = { + codeActionLiteralSupport = { + codeActionKind = { + valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } + } + }, + dataSupport = true, + dynamicRegistration = true, + isPreferredSupport = true, + resolveSupport = { + properties = { "edit", "command" } + } + }, + codeLens = { + dynamicRegistration = false, + resolveSupport = { + properties = { "command" } + } + }, + completion = { + completionItem = { + commitCharactersSupport = false, + deprecatedSupport = true, + documentationFormat = { "markdown", "plaintext" }, + preselectSupport = false, + resolveSupport = { + properties = { "additionalTextEdits", "command" } + }, + snippetSupport = true, + tagSupport = { + valueSet = { 1 } + } + }, + completionItemKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } + }, + completionList = { + itemDefaults = { "editRange", "insertTextFormat", "insertTextMode", "data" } + }, + contextSupport = true, + dynamicRegistration = false + }, + declaration = { + linkSupport = true + }, + definition = { + dynamicRegistration = true, + linkSupport = true + }, + diagnostic = { + dynamicRegistration = false + }, + documentHighlight = { + dynamicRegistration = false + }, + documentSymbol = { + dynamicRegistration = false, + hierarchicalDocumentSymbolSupport = true, + symbolKind = { + valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } + } + }, + foldingRange = { + dynamicRegistration = false, + foldingRange = { + collapsedText = true + }, + lineFoldingOnly = true + }, + formatting = { + dynamicRegistration = true + }, + hover = { + contentFormat = { "markdown", "plaintext" }, + dynamicRegistration = true + }, + implementation = { + linkSupport = true + }, + inlayHint = { + dynamicRegistration = true, + resolveSupport = { + properties = { "textEdits", "tooltip", "location", "command" } + } + }, + publishDiagnostics = { + dataSupport = true, + relatedInformation = true, + tagSupport = { + valueSet = { 1, 2 } + } + }, + rangeFormatting = { + dynamicRegistration = true, + rangesSupport = true + }, + references = { + dynamicRegistration = false + }, + rename = { + dynamicRegistration = true, + prepareSupport = true + }, + semanticTokens = { + augmentsSyntaxTokens = true, + dynamicRegistration = false, + formats = { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = true, + requests = { + full = { + delta = true + }, + range = false + }, + serverCancelSupport = false, + tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, + tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } + }, + signatureHelp = { + dynamicRegistration = false, + signatureInformation = { + activeParameterSupport = true, + documentationFormat = { "markdown", "plaintext" }, + parameterInformation = { + labelOffsetSupport = true + } + } + }, + synchronization = { + didSave = true, + dynamicRegistration = false, + willSave = true, + willSaveWaitUntil = true + }, + typeDefinition = { + linkSupport = true + } + }, + window = { + showDocument = { + support = true + }, + showMessage = { + messageActionItem = { + additionalPropertiesSupport = true + } + }, + workDoneProgress = true + }, + workspace = { + workspaceFolders = true + } + }, + cmd = { "node", "C:\\Users\\antoi\\AppData\\Local\\nvim-data\\lazy\\copilot.lua\\copilot\\js\\language-server.js", "--stdio" }, + get_language_id = , + handlers = { + PanelSolution = , + PanelSolutionsDone = , + statusNotification = + }, + init_options = { + editorInfo = { + name = "Neovim", + version = "0.11.0" + }, + editorPluginInfo = { + name = "copilot.lua", + version = "1.295.0" + } + }, + name = "copilot", + on_exit = , + on_init = , + root_dir = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + settings = { + telemetry = { + telemetryLevel = "all" + } + }, + workspace_folders = { { + name = "C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua", + uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua" + } } +} +2025-04-04 21:29:30.085 [3] [TRACE]: attaching to buffer +2025-04-04 21:29:30.095 [4] [TRACE]: buffer attached +2025-04-04 21:29:30.318 [5] [TRACE]: api notify: +"workspace/didChangeConfiguration" +{ + settings = { + disabledLanguages = {}, + enableAutoCompletions = true, + github = { + copilot = { + selectedCompletionModel = "" + } + } + } +} +2025-04-04 21:29:30.319 [6] [TRACE]: workspace configuration +{ + settings = { + disabledLanguages = {}, + enableAutoCompletions = true, + github = { + copilot = { + selectedCompletionModel = "" + } + } + } +} +2025-04-04 21:29:30.319 [7] [TRACE]: api notify: +"$/setTrace" +{ + value = "off" +} +2025-04-04 21:29:30.601 [8] [TRACE]: suggestion on insert enter +2025-04-04 21:29:30.601 [10] [TRACE]: suggestion context +2025-04-04 21:29:30.601 [11] [TRACE]: suggestion new context +{} +2025-04-04 21:29:30.601 [9] [TRACE]: suggestion schedule +2025-04-04 21:29:30.601 [12] [TRACE]: suggestion update preview +{} +2025-04-04 21:29:30.601 [13] [TRACE]: suggestion get current suggestion +{} +2025-04-04 21:29:30.601 [14] [TRACE]: suggestion current suggestion +{} +2025-04-04 21:29:30.601 [15] [TRACE]: suggestion clear preview +2025-04-04 21:29:30.601 [16] [TRACE]: suggestion context +{} +2025-04-04 21:29:30.601 [19] [TRACE]: suggestion cancel inflight requests +{} +2025-04-04 21:29:30.601 [17] [TRACE]: suggestion on cursor moved insert +2025-04-04 21:29:30.601 [18] [TRACE]: suggestion schedule +{} +2025-04-04 21:29:30.601 [20] [TRACE]: suggestion stop timer +2025-04-04 21:29:30.601 [21] [TRACE]: suggestion update preview +{} +2025-04-04 21:29:30.601 [22] [TRACE]: suggestion get current suggestion +{} +2025-04-04 21:29:30.602 [23] [TRACE]: suggestion current suggestion +{} +2025-04-04 21:29:30.602 [24] [TRACE]: suggestion clear preview +2025-04-04 21:29:30.602 [25] [TRACE]: suggestion clear +2025-04-04 21:29:30.602 [26] [TRACE]: suggestion context +{} +2025-04-04 21:29:30.602 [27] [TRACE]: suggestion stop timer +2025-04-04 21:29:30.602 [28] [TRACE]: suggestion cancel inflight requests +{} +2025-04-04 21:29:30.602 [29] [TRACE]: suggestion update preview +{} +2025-04-04 21:29:30.602 [30] [TRACE]: suggestion get current suggestion +{} +2025-04-04 21:29:30.602 [32] [TRACE]: suggestion clear preview +2025-04-04 21:29:30.602 [31] [TRACE]: suggestion current suggestion +{} +2025-04-04 21:29:30.603 [35] [TRACE]: suggestion schedule +2025-04-04 21:29:30.602 [33] [TRACE]: suggestion reset context +{} +2025-04-04 21:29:30.603 [34] [TRACE]: suggestion on insert enter +2025-04-04 21:29:30.603 [36] [TRACE]: suggestion context +{} +2025-04-04 21:29:30.603 [37] [TRACE]: suggestion update preview +{} +2025-04-04 21:29:30.603 [39] [TRACE]: suggestion current suggestion +{} +2025-04-04 21:29:30.603 [38] [TRACE]: suggestion get current suggestion +{} +2025-04-04 21:29:30.603 [40] [TRACE]: suggestion clear preview +2025-04-04 21:29:30.603 [44] [TRACE]: suggestion cancel inflight requests +{} +2025-04-04 21:29:30.603 [41] [TRACE]: suggestion context +{} +2025-04-04 21:29:30.603 [43] [TRACE]: suggestion schedule +{} +2025-04-04 21:29:30.603 [42] [TRACE]: suggestion on cursor moved insert +2025-04-04 21:29:30.603 [45] [TRACE]: suggestion stop timer +2025-04-04 21:29:30.603 [46] [TRACE]: suggestion update preview +{} +2025-04-04 21:29:30.603 [47] [TRACE]: suggestion get current suggestion +{} +2025-04-04 21:29:30.603 [49] [TRACE]: suggestion clear preview +2025-04-04 21:29:30.603 [48] [TRACE]: suggestion current suggestion +{} +2025-04-04 21:29:31.623 [50] [TRACE]: suggestion schedule timer +1 +2025-04-04 21:29:31.623 [52] [TRACE]: suggestion complete +2025-04-04 21:29:31.623 [51] [TRACE]: suggestion trigger +1 +2025-04-04 21:29:31.623 [54] [TRACE]: api request: +"getCompletions" +{ + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 3, + line = 1 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 5 + }, + position = , + textDocument = { + relativePath = "", + uri = "file://", + version = 5 + } +} +2025-04-04 21:29:31.623 [53] [TRACE]: suggestion context +{} +2025-04-04 21:29:31.628 [55] [TRACE]: suggestion clear +2025-04-04 21:29:31.628 [57] [TRACE]: suggestion cancel inflight requests +{ + first = 2, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 3, + line = 1 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 5 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 5 + } + } +} +2025-04-04 21:29:31.628 [56] [TRACE]: suggestion context +{ + first = 2, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 3, + line = 1 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 5 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 5 + } + } +} +2025-04-04 21:29:31.628 [58] [TRACE]: suggestion cancel first request +2025-04-04 21:29:31.628 [59] [TRACE]: suggestion update preview +{ + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 3, + line = 1 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 5 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 5 + } + } +} +2025-04-04 21:29:31.628 [61] [TRACE]: suggestion current suggestion +{ + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 3, + line = 1 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 5 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 5 + } + } +} +2025-04-04 21:29:31.628 [62] [TRACE]: suggestion clear preview +2025-04-04 21:29:31.628 [60] [TRACE]: suggestion get current suggestion +{ + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 3, + line = 1 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 5 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 5 + } + } +} +2025-04-04 21:29:31.628 [63] [TRACE]: suggestion reset context +{ + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 3, + line = 1 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 5 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 5 + } + } +} +2025-04-04 21:29:31.630 [65] [TRACE]: suggestion schedule +2025-04-04 21:29:31.630 [64] [TRACE]: suggestion on insert enter +2025-04-04 21:29:31.630 [67] [TRACE]: suggestion update preview +{} +2025-04-04 21:29:31.630 [66] [TRACE]: suggestion context +{} +2025-04-04 21:29:31.630 [69] [TRACE]: suggestion current suggestion +{} +2025-04-04 21:29:31.630 [68] [TRACE]: suggestion get current suggestion +{} +2025-04-04 21:29:31.630 [70] [TRACE]: suggestion clear preview +2025-04-04 21:29:31.630 [73] [TRACE]: suggestion schedule +{} +2025-04-04 21:29:31.630 [71] [TRACE]: suggestion context +{} +2025-04-04 21:29:31.630 [75] [TRACE]: suggestion stop timer +2025-04-04 21:29:31.630 [72] [TRACE]: suggestion on cursor moved insert +2025-04-04 21:29:31.630 [77] [TRACE]: suggestion get current suggestion +{} +2025-04-04 21:29:31.630 [74] [TRACE]: suggestion cancel inflight requests +{} +2025-04-04 21:29:31.630 [76] [TRACE]: suggestion update preview +{} +2025-04-04 21:29:31.630 [78] [TRACE]: suggestion current suggestion +{} +2025-04-04 21:29:31.630 [79] [TRACE]: suggestion clear preview +2025-04-04 21:29:31.655 [83] [TRACE]: suggestion context +{} +2025-04-04 21:29:31.655 [80] [TRACE]: suggestion schedule timer +1 +2025-04-04 21:29:31.655 [84] [TRACE]: api request: +"getCompletions" +{ + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } +} +2025-04-04 21:29:31.655 [82] [TRACE]: suggestion complete +2025-04-04 21:29:31.655 [81] [TRACE]: suggestion trigger +1 +2025-04-04 21:29:31.298 [85] [TRACE]: suggestion handle trigger request +{ + completions = {} +} +2025-04-04 21:29:31.298 [86] [TRACE]: suggestion context +{ + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + } +} +2025-04-04 21:29:31.298 [87] [TRACE]: suggestion context +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = {}, + suggestions = {} +} +2025-04-04 21:29:31.298 [88] [TRACE]: suggestion update preview +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = {}, + suggestions = {} +} +2025-04-04 21:29:31.298 [89] [TRACE]: suggestion get current suggestion +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = {}, + suggestions = {} +} +2025-04-04 21:29:31.298 [90] [TRACE]: suggestion current suggestion +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = {}, + suggestions = {} +} +2025-04-04 21:29:31.298 [91] [TRACE]: suggestion clear preview +2025-04-04 21:29:32.687 [93] [TRACE]: suggestion context +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = {}, + suggestions = {} +} +2025-04-04 21:29:32.688 [94] [TRACE]: suggestion context +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = {}, + suggestions = { { + displayText = "89", + docVersion = 7, + position = { + character = 1, + line = 2 + }, + range = { + ["end"] = { + character = 1, + line = 2 + }, + start = { + character = 0, + line = 2 + } + }, + text = "789", + uuid = "13a692e0-587d-4d54-8320-5a7c5dc67696" + } } +} +2025-04-04 21:29:32.688 [95] [TRACE]: suggestion update preview +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = {}, + suggestions = { { + displayText = "89", + docVersion = 7, + position = { + character = 1, + line = 2 + }, + range = { + ["end"] = { + character = 1, + line = 2 + }, + start = { + character = 0, + line = 2 + } + }, + text = "789", + uuid = "13a692e0-587d-4d54-8320-5a7c5dc67696" + } } +} +2025-04-04 21:29:32.688 [96] [TRACE]: suggestion get current suggestion +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = {}, + suggestions = { { + displayText = "89", + docVersion = 7, + position = { + character = 1, + line = 2 + }, + range = { + ["end"] = { + character = 1, + line = 2 + }, + start = { + character = 0, + line = 2 + } + }, + text = "789", + uuid = "13a692e0-587d-4d54-8320-5a7c5dc67696" + } } +} +2025-04-04 21:29:32.688 [97] [TRACE]: suggestion current suggestion +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = {}, + suggestions = { { + displayText = "89", + docVersion = 7, + position = { + character = 1, + line = 2 + }, + range = { + ["end"] = { + character = 1, + line = 2 + }, + start = { + character = 0, + line = 2 + } + }, + text = "789", + uuid = "13a692e0-587d-4d54-8320-5a7c5dc67696" + } } +} +2025-04-04 21:29:32.687 [92] [TRACE]: suggestion handle trigger request +{ + completions = { { + displayText = "89", + docVersion = 7, + position = { + character = 1, + line = 2 + }, + range = { + ["end"] = { + character = 1, + line = 2 + }, + start = { + character = 0, + line = 2 + } + }, + text = "789", + uuid = "13a692e0-587d-4d54-8320-5a7c5dc67696" + } } +} +2025-04-04 21:29:32.688 [98] [TRACE]: suggestion clear preview +2025-04-04 21:29:32.688 [99] [TRACE]: api request: +"notifyShown" +{ + uuid = "13a692e0-587d-4d54-8320-5a7c5dc67696" +} +2025-04-04 21:29:34.652 [100] [TRACE]: suggestion context +{ + choice = 1, + first = 3, + params = { + _ = true, + doc = { + indentSize = 8, + insertSpaces = false, + position = <1>{ + character = 1, + line = 2 + }, + relativePath = "", + tabSize = 8, + uri = "file://", + version = 7 + }, + position =
, + textDocument = { + relativePath = "", + uri = "file://", + version = 7 + } + }, + shown_choices = { + ["13a692e0-587d-4d54-8320-5a7c5dc67696"] = true + }, + suggestions = { { + displayText = "89", + docVersion = 7, + position = { + character = 1, + line = 2 + }, + range = { + ["end"] = { + character = 1, + line = 2 + }, + start = { + character = 0, + line = 2 + } + }, + text = "789", + uuid = "13a692e0-587d-4d54-8320-5a7c5dc67696" + } } +} +2025-04-04 21:29:34.653 [101] [TRACE]: api request: +"notifyRejected" +{ + uuids = { "13a692e0-587d-4d54-8320-5a7c5dc67696" } +} +2025-04-04 21:29:34.653 [102] [TRACE]: suggestion context +2025-04-04 21:29:34.653 [103] [TRACE]: suggestion new context +{} diff --git a/tests/screenshots/tests-test_suggestion.lua---suggestion()---suggestion-works b/tests/screenshots/tests-test_suggestion.lua---suggestion()---suggestion-works new file mode 100644 index 00000000..97ea2b0d --- /dev/null +++ b/tests/screenshots/tests-test_suggestion.lua---suggestion()---suggestion-works @@ -0,0 +1,23 @@ +--|---------|----- +01|123 +02|456 +03|789 +04|~ +05|~ +06|~ +07|~ +08|~ +09|", "o456", "", "o7") + child.lua("p.toggle()") + + local i = 0 + local lines = "" + while i < 50 do + vim.loop.sleep(200) + child.lua("vim.wait(0)") + lines = child.api.nvim_buf_get_lines(2, 4, 5, false) + if lines[1] == "789" then + break + end + i = i + 1 + end + + eq(lines[1], "789") +end + +return T diff --git a/tests/test_suggestion.lua b/tests/test_suggestion.lua new file mode 100644 index 00000000..895e4855 --- /dev/null +++ b/tests/test_suggestion.lua @@ -0,0 +1,54 @@ +-- local eq = MiniTest.expect.equality +-- local neq = MiniTest.expect.no_equality +local reference_screenshot = MiniTest.expect.reference_screenshot +local child = MiniTest.new_child_neovim() +-- local u = require("tests.utils") + +local T = MiniTest.new_set({ + hooks = { + pre_once = function() + if vim.fn.filereadable("./tests/logs/test_suggestion.log") == 1 then + vim.fn.delete("./tests/logs/test_suggestion.log") + end + end, + pre_case = function() + child.restart({ "-u", "tests/scripts/minimal_init.lua" }) + child.bo.readonly = false + child.lua("M = require('copilot')") + child.lua("cmd = require('copilot.command')") + -- child.lua([[require("osv").launch({ port = 8086 })]]) + end, + post_once = child.stop, + }, +}) + +T["suggestion()"] = MiniTest.new_set() + +-- TODO: Need means of watching for the suggestion to popup and not randomly wait x ms +-- Should be able to use the screenshot to parsse for the suggesetion, u.get_lines does not work +-- Also, this test can fail if the LSP is taking more time than usual and re-running it passes +T["suggestion()"]["suggestion works"] = function() + child.o.lines, child.o.columns = 10, 15 + child.lua([[M.setup({ + suggestion = { + auto_trigger = true, + }, + logger = { + file_log_level = vim.log.levels.TRACE, + file = "./tests/logs/test_suggestion.log", + }, + filetypes = { + ["*"] = true, + }, + })]]) + + -- look for a synchronous way to wait for engine to be up + vim.loop.sleep(500) + child.type_keys("i123", "", "o456", "", "o7") + vim.loop.sleep(3000) + child.lua("vim.wait(0)") + + reference_screenshot(child.get_screenshot()) +end + +return T diff --git a/tests/utils.lua b/tests/utils.lua new file mode 100644 index 00000000..c60a79bd --- /dev/null +++ b/tests/utils.lua @@ -0,0 +1,90 @@ +local M = { + expect_match = MiniTest.new_expectation( + -- Expectation subject + "string matching", + -- Predicate + ---@param str string|number + ---@param pattern string|number + function(str, pattern) + return str:find(pattern) ~= nil + end, + -- Fail context + ---@param str string|number + ---@param pattern string|number + function(str, pattern) + return string.format("Pattern: %s\nObserved string: %s", vim.inspect(pattern), str) + end + ), + expect_no_match = MiniTest.new_expectation( + -- Expectation subject + "no string matching", + -- Predicate + ---@param str string|number + ---@param pattern string|number + function(str, pattern) + return str:find(pattern) == nil + end, + -- Fail context + ---@param str string|number + ---@param pattern string|number + function(str, pattern) + return string.format("Pattern: %s\nObserved string: %s", vim.inspect(pattern), str) + end + ), + expect_not_empty = MiniTest.new_expectation( + -- Expectation subject + "not empty", + -- Predicate + ---@param val any|nil + function(val) + if val == nil or val == vim.NIL then + return false + end + + if type(val) == "string" then + return val ~= "" + elseif type(val) == "table" then + return val ~= {} + end + + return true + end, + -- Fail context + ---@param _ any|nil + function(_) + return "Expected value to be not empty" + end + ), + expect_empty = MiniTest.new_expectation( + -- Expectation subject + "empty", + -- Predicate + ---@param val any|nil + function(val) + if val == nil or val == vim.NIL then + return true + end + + if type(val) == "string" then + return val == "" + elseif type(val) == "table" then + return val == {} + end + + return false + end, + -- Fail context + ---@param val any|nil + function(val) + return "Expected value to be empty\nObserved value: " .. vim.inspect(val) + end + ), + set_lines = function(child, lines) + child.api.nvim_buf_set_lines(0, 0, -1, true, lines) + end, + get_lines = function(child) + return child.api.nvim_buf_get_lines(0, 0, -1, true) + end, +} + +return M From 14fb80f467e1c4297a72d0c5513588ca3591d25a Mon Sep 17 00:00:00 2001 From: Antoine Gaudreau Simard Date: Sat, 5 Apr 2025 09:43:03 -0400 Subject: [PATCH 6/7] fix: binary lsp not starting --- lua/copilot/lsp/binary.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/copilot/lsp/binary.lua b/lua/copilot/lsp/binary.lua index 90671d91..0c84397b 100644 --- a/lua/copilot/lsp/binary.lua +++ b/lua/copilot/lsp/binary.lua @@ -364,6 +364,8 @@ function M.setup(custom_server_path) M.initialized = true end + + M.init() end return M From 0e0630ca5edb2c5e0cd6164c8dfc738425e4e332 Mon Sep 17 00:00:00 2001 From: LUSEDOU <107129219+LUSEDOU@users.noreply.github.com> Date: Sat, 5 Apr 2025 09:35:22 -0500 Subject: [PATCH 7/7] feat(suggestion): accept keypress Copilot bypass (#258) Allows passing the keypress to the buffer without triggering Copilot logic when the suggestion is not visible. This will work better if trigger_on_accept is false. Co-authored-by: Antoine Gaudreau Simard --- README.md | 2 + lua/copilot/config/suggestion.lua | 3 + lua/copilot/suggestion/init.lua | 13 ++- lua/copilot/util.lua | 1 + ...p,-no-suggestion,-execute-normal-keystroke | 23 ++++++ ...ion()---accept-keymap-to-trigger-sugestion | 23 ++++++ ...trigger-is-false,-will-not-show-ghost-test | 23 ++++++ tests/test_suggestion.lua | 79 +++++++++++++++++++ 8 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 tests/screenshots/tests-test_suggestion.lua---suggestion()---accept-keymap,-no-suggestion,-execute-normal-keystroke create mode 100644 tests/screenshots/tests-test_suggestion.lua---suggestion()---accept-keymap-to-trigger-sugestion create mode 100644 tests/screenshots/tests-test_suggestion.lua---suggestion()---auto_trigger-is-false,-will-not-show-ghost-test diff --git a/README.md b/README.md index f863bc88..edd4b1c8 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ require('copilot').setup({ auto_trigger = false, hide_during_completion = true, debounce = 75, + trigger_on_accept = true, keymap = { accept = "", accept_word = false, @@ -171,6 +172,7 @@ require("copilot.panel").refresh() When `auto_trigger` is `true`, copilot starts suggesting as soon as you enter insert mode. When `auto_trigger` is `false`, use the `next`, `prev` or `accept` keymap to trigger copilot suggestion. +When `trigger_on_accept` is `false`, the keypress will be passed to the buffer as-is, instead of triggering completion. To toggle auto trigger for the current buffer, use `require("copilot.suggestion").toggle_auto_trigger()`. diff --git a/lua/copilot/config/suggestion.lua b/lua/copilot/config/suggestion.lua index 7c719ef3..e97fde21 100644 --- a/lua/copilot/config/suggestion.lua +++ b/lua/copilot/config/suggestion.lua @@ -3,6 +3,7 @@ ---@field auto_trigger boolean Whether to trigger the suggestion automatically ---@field hide_during_completion boolean Whether to hide the suggestion during completion ---@field debounce integer Debounce time in milliseconds +---@field trigger_on_accept boolean To either trigger the suggestion on accept or pass the keystroke to the buffer ---@field keymap SuggestionKeymapConfig Keymap for the suggestion ---@class (exact) SuggestionKeymapConfig @@ -20,6 +21,7 @@ local suggestion = { auto_trigger = false, hide_during_completion = true, debounce = 15, + trigger_on_accept = true, keymap = { accept = "", accept_word = false, @@ -36,6 +38,7 @@ function suggestion.validate(config) vim.validate("auto_trigger", config.auto_trigger, "boolean") vim.validate("hide_during_completion", config.hide_during_completion, "boolean") vim.validate("debounce", config.debounce, { "number", "nil" }) + vim.validate("trigger_on_accept", config.trigger_on_accept, "boolean") vim.validate("keymap", config.keymap, "table") vim.validate("keymap.accept", config.keymap.accept, { "string", "boolean" }) vim.validate("keymap.accept_word", config.keymap.accept_word, { "string", "boolean" }) diff --git a/lua/copilot/suggestion/init.lua b/lua/copilot/suggestion/init.lua index 22ffcfea..291bc251 100644 --- a/lua/copilot/suggestion/init.lua +++ b/lua/copilot/suggestion/init.lua @@ -70,7 +70,16 @@ end local function set_keymap(keymap) if keymap.accept then - vim.keymap.set("i", keymap.accept, M.accept, { + vim.keymap.set("i", keymap.accept, function() + local ctx = get_ctx() + -- If we trigger on accept but the suggestion has not been triggered yet, we let it go through so it does + if (config.suggestion.trigger_on_accept and not ctx.first) or M.is_visible() then + M.accept() + else + local termcode = vim.api.nvim_replace_termcodes(keymap.accept, true, false, true) + vim.api.nvim_feedkeys(termcode, "n", true) + end + end, { desc = "[copilot] accept suggestion", silent = true, }) @@ -475,7 +484,7 @@ function M.accept(modifier) logger.trace("suggestion accept", ctx) -- no suggestion request yet - if not ctx.first then + if (not ctx.first) and config.suggestion.trigger_on_accept then logger.trace("suggestion accept, not first request", ctx) schedule(ctx) return diff --git a/lua/copilot/util.lua b/lua/copilot/util.lua index 3f2d8ff3..24c151a1 100644 --- a/lua/copilot/util.lua +++ b/lua/copilot/util.lua @@ -77,6 +77,7 @@ function M.get_doc() return doc end +-- Used by copilot.cmp to watch out if moving it function M.get_doc_params(overrides) overrides = overrides or {} diff --git a/tests/screenshots/tests-test_suggestion.lua---suggestion()---accept-keymap,-no-suggestion,-execute-normal-keystroke b/tests/screenshots/tests-test_suggestion.lua---suggestion()---accept-keymap,-no-suggestion,-execute-normal-keystroke new file mode 100644 index 00000000..4a7f7b7a --- /dev/null +++ b/tests/screenshots/tests-test_suggestion.lua---suggestion()---accept-keymap,-no-suggestion,-execute-normal-keystroke @@ -0,0 +1,23 @@ +--|---------|----- +01|123 +02|456 +03|7 +04|~ +05|~ +06|~ +07|~ +08|~ +09|", "o456", "", "o7") + vim.loop.sleep(3000) + child.lua("vim.wait(0)") + + reference_screenshot(child.get_screenshot()) +end + +T["suggestion()"]["accept keymap to trigger sugestion"] = function() + child.o.lines, child.o.columns = 10, 15 + child.lua([[M.setup({ + suggestion = { + auto_trigger = false, + keymap = { + accept = "", + }, + }, + logger = { + file_log_level = vim.log.levels.TRACE, + file = "./tests/logs/test_suggestion.log", + }, + filetypes = { + ["*"] = true, + }, + })]]) + + -- look for a synchronous way to wait for engine to be up + vim.loop.sleep(500) + child.type_keys("i123", "", "o456", "", "o7", "") + vim.loop.sleep(3000) + child.lua("vim.wait(0)") + + reference_screenshot(child.get_screenshot()) +end + +T["suggestion()"]["accept keymap, no suggestion, execute normal keystroke"] = function() + child.o.lines, child.o.columns = 10, 15 + child.lua([[M.setup({ + suggestion = { + auto_trigger = false, + trigger_on_accept = false, + keymap = { + accept = "", + }, + }, + logger = { + file_log_level = vim.log.levels.TRACE, + file = "./tests/logs/test_suggestion.log", + }, + filetypes = { + ["*"] = true, + }, + })]]) + + -- look for a synchronous way to wait for engine to be up + vim.loop.sleep(500) + child.type_keys("i123", "", "o456", "", "o7", "") + vim.loop.sleep(3000) + child.lua("vim.wait(0)") + + reference_screenshot(child.get_screenshot()) +end + return T