diff --git a/.github/workflows/selene.yml b/.github/workflows/selene.yml new file mode 100644 index 00000000..d9198149 --- /dev/null +++ b/.github/workflows/selene.yml @@ -0,0 +1,22 @@ +name: Selene check + +on: + push: + branches: + - "main" + paths: + - "lua/**/*.lua" + - "plugin/*.lua" + pull_request: + +jobs: + selene: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run Selene check + uses: NTBBloodbath/selene-action@v1.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: lua/ + version: 0.28.0 diff --git a/Makefile b/Makefile index 1daeeecb..53babd00 100644 --- a/Makefile +++ b/Makefile @@ -19,3 +19,8 @@ coverage: pdm run coverage run -m pytest; \ pdm run coverage html; \ pdm run coverage report -m + +lint: + pdm run ruff check src/**/*.py; \ + pdm run basedpyright src/**/*.py; \ + selene lua/**/*.lua plugin/*.lua diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 7a7c4939..cabbb293 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -22,7 +22,8 @@ them locally before you open the PR. This project also runs static analysis with [basedpyright](https://docs.basedpyright.com). GitHub Action will also run the -check when a PR is submitted. +check when a PR is submitted. This, as well as `ruff check`, are both included +in `make lint`. You may also find it helpful to [enable logging](https://github.com/Davidyz/VectorCode/blob/main/docs/cli.md#debugging-and-diagnosing) @@ -35,6 +36,9 @@ formatted (stylua) and appropriately type-annotated, you're good. I do have plans to write some tests, but before that happens, formatting and type annotations are the only things that you need to take special care of. +The lua codebase is linted by [selene](https://github.com/Kampfkarren/selene). +You may run `make lint` or call `selene` from the CLI to lint the code. + You may find it useful to [enable logging](https://github.com/Davidyz/VectorCode/blob/main/docs/cli.md#debugging-and-diagnosing) when you're poking around the codebase. diff --git a/lua/vectorcode/cacher/default.lua b/lua/vectorcode/cacher/default.lua index 0788dcc4..2b5d9850 100644 --- a/lua/vectorcode/cacher/default.lua +++ b/lua/vectorcode/cacher/default.lua @@ -77,7 +77,7 @@ local function async_runner(query_message, buf_nr) end logger.debug("vectorcode ", buf_name, " default cacher results: ", json_result) CACHE[buf_nr].job_count = CACHE[buf_nr].job_count - 1 - assert(job_pid ~= nil) + assert(job_pid ~= nil, "Failed to fetch the job pid.") CACHE[buf_nr].jobs[job_pid] = nil if exit_code ~= 0 then @@ -189,7 +189,7 @@ M.register_buffer = vc_config.check_cli_wrap( or (vim.uv.clock_gettime("realtime").sec - cache.last_run) > opts.debounce then local cb = cache.options.query_cb - assert(type(cb) == "function") + assert(type(cb) == "function", "`cb` should be a function.") async_runner(cb(bufnr), bufnr) end end, @@ -249,7 +249,7 @@ M.buf_is_registered = function(bufnr) if bufnr == 0 or bufnr == nil then bufnr = vim.api.nvim_get_current_buf() end - return type(CACHE[bufnr]) == "table" and CACHE[bufnr] ~= {} + return type(CACHE[bufnr]) == "table" and not vim.tbl_isempty(CACHE[bufnr]) end M.query_from_cache = vc_config.check_cli_wrap( diff --git a/lua/vectorcode/cacher/lsp.lua b/lua/vectorcode/cacher/lsp.lua index bc5bcca5..df9abe68 100644 --- a/lua/vectorcode/cacher/lsp.lua +++ b/lua/vectorcode/cacher/lsp.lua @@ -23,7 +23,7 @@ local client_id = nil ---@param project_root string ---@return string? local function check_project_root(bufnr, project_root) - assert(bufnr ~= 0) + assert(bufnr ~= 0, "Need a non-zero bufnr") if project_root == nil then local cwd = vim.uv.cwd() or "." local result = vim.fs.root(cwd, ".vectorcode") or vim.fs.root(cwd, ".git") @@ -76,7 +76,7 @@ local function kill_jobs(bufnr) if client == nil then return end - for request_id, time in pairs(CACHE[bufnr].jobs) do + for request_id, _ in pairs(CACHE[bufnr].jobs) do job_runner.stop_job(request_id) end cleanup_lsp_requests() @@ -93,7 +93,7 @@ local function async_runner(query_message, buf_nr) buf_name = vim.api.nvim_buf_get_name(buf_nr) logger.debug("Started lsp cacher job on :", buf_name) end) - assert(client_id ~= nil) + assert(client_id ~= nil, "LSP client hasn't been initialised.") ---@type VectorCode.Cache local cache = CACHE[buf_nr] local args = { diff --git a/lua/vectorcode/config.lua b/lua/vectorcode/config.lua index 9fcc84f5..c447d97c 100644 --- a/lua/vectorcode/config.lua +++ b/lua/vectorcode/config.lua @@ -130,7 +130,7 @@ return { logger.info("Received setup opts:\n", opts) opts = opts or {} setup_config = vim.tbl_deep_extend("force", config, opts or {}) - for k, v in pairs(setup_config.async_opts) do + for k, _ in pairs(setup_config.async_opts) do if setup_config[k] ~= nil and (opts.async_opts == nil or opts.async_opts[k] == nil) diff --git a/lua/vectorcode/init.lua b/lua/vectorcode/init.lua index d0bbf350..a92d88e1 100644 --- a/lua/vectorcode/init.lua +++ b/lua/vectorcode/init.lua @@ -79,14 +79,15 @@ M.vectorise = vc_config.check_cli_wrap( function(files, project_root) logger.info("vectorcode.vectorise: ", files, project_root) local args = { "--pipe", "vectorise" } - if project_root ~= nil then - vim.list_extend(args, { "--project_root", project_root }) - elseif - M.check("config", function(obj) - if obj.code == 0 then - project_root = obj.stdout - end - end) + if + project_root ~= nil + or ( + M.check("config", function(obj) + if obj.code == 0 then + project_root = obj.stdout + end + end) + ) then vim.list_extend(args, { "--project_root", project_root }) end @@ -203,7 +204,7 @@ end ---@return string[] M.prompts = vc_config.check_cli_wrap(function() local result, error = jobrunner.run({ "prompts", "-p" }, -1, 0) - if result == nil or result == {} then + if result == nil or vim.tbl_isempty(result) then logger.warn(vim.inspect(error)) if vc_config.get_user_config().notify then notify(vim.inspect(error)) diff --git a/lua/vectorcode/integrations/codecompanion/func_calling_tool.lua b/lua/vectorcode/integrations/codecompanion/func_calling_tool.lua index cce8a57a..14d6e313 100644 --- a/lua/vectorcode/integrations/codecompanion/func_calling_tool.lua +++ b/lua/vectorcode/integrations/codecompanion/func_calling_tool.lua @@ -37,12 +37,11 @@ return check_cli_wrap(function(opts) cmds = { ---@param agent CodeCompanion.Agent ---@param action table - ---@param input table ---@return nil|{ status: string, msg: string } - function(agent, action, input, cb) + function(agent, action, _, cb) logger.info("CodeCompanion tool called with the following arguments:\n", action) job_runner = cc_common.initialise_runner(opts.use_lsp) - assert(job_runner ~= nil) + assert(job_runner ~= nil, "Jobrunner not initialised!") assert( type(cb) == "function", "Please upgrade CodeCompanion.nvim to at least 13.5.0" diff --git a/lua/vectorcode/integrations/copilotchat.lua b/lua/vectorcode/integrations/copilotchat.lua index 0f470bf2..5be57abb 100644 --- a/lua/vectorcode/integrations/copilotchat.lua +++ b/lua/vectorcode/integrations/copilotchat.lua @@ -37,7 +37,7 @@ end ---@async local run_job = async.wrap(function(args, use_lsp, bufnr, callback) local runner = get_runner(use_lsp) - assert(runner ~= nil) + assert(runner ~= nil, "Failed to initialize the runner!") runner.run_async(args, callback, bufnr) end, 4) diff --git a/lua/vectorcode/jobrunner/lsp.lua b/lua/vectorcode/jobrunner/lsp.lua index 14e100b3..69d165a6 100644 --- a/lua/vectorcode/jobrunner/lsp.lua +++ b/lua/vectorcode/jobrunner/lsp.lua @@ -39,17 +39,17 @@ end function jobrunner.run(args, timeout_ms, bufnr) jobrunner.init(false) - assert(CLIENT ~= nil) - assert(bufnr ~= nil) + assert(CLIENT ~= nil, "Failed to initialize the LSP server!") + assert(bufnr ~= nil, "Need to pass the buffer number!") if timeout_ms == nil or timeout_ms < 0 then timeout_ms = 2 ^ 31 - 1 end args = require("vectorcode.jobrunner").find_root(args, bufnr) local result, err, code - jobrunner.run_async(args, function(res, err, e_code) + jobrunner.run_async(args, function(res, e, e_code) result = res - err = err + err = e code = e_code end, bufnr) vim.wait(timeout_ms, function() @@ -60,7 +60,7 @@ end function jobrunner.run_async(args, callback, bufnr) assert(jobrunner.init(false)) - assert(bufnr ~= nil) + assert(bufnr ~= nil, "Need to pass the buffer number!") if not CLIENT.attached_buffers[bufnr] then if vim.lsp.buf_attach_client(bufnr, CLIENT.id) then local uri = vim.uri_from_bufnr(bufnr) diff --git a/lua/vectorcode/types.lua b/lua/vectorcode/types.lua index cea3c75b..55e7504d 100644 --- a/lua/vectorcode/types.lua +++ b/lua/vectorcode/types.lua @@ -14,10 +14,10 @@ ---Type definitions for options accepted by `query` API. ---@class VectorCode.QueryOpts ----@field exclude_this boolean Whether to exclude the current buffer. Default: true ----@field n_query integer Number of results. ----@field notify boolean Notify on new results and other key moments. ----@field timeout_ms number Timeout (in milliseconds) for running a vectorcode command. Default: 5000 +---@field exclude_this boolean? Whether to exclude the current buffer. Default: true +---@field n_query integer? Number of results. +---@field notify boolean? Notify on new results and other key moments. +---@field timeout_ms number? Timeout (in milliseconds) for running a vectorcode command. Default: 5000 ---@class VectorCode.OnSetup Some actions that may be configured to run when `setup` is called. ---@field update boolean `vectorcode update` diff --git a/lua/vectorcode/utils.lua b/lua/vectorcode/utils.lua index 7ddea429..341c96cc 100644 --- a/lua/vectorcode/utils.lua +++ b/lua/vectorcode/utils.lua @@ -8,13 +8,13 @@ local function traverse(node, cb) traverse(node.result, cb) end if vim.isarray(node) then - for k, v in pairs(node) do + for _, v in pairs(node) do traverse(v, cb) end return end if vim.isarray(node.children) then - for k, v in pairs(node.children) do + for _, v in pairs(node.children) do traverse(v, cb) end end @@ -47,7 +47,7 @@ function M.make_lsp_document_symbol_cb() return M.make_surrounding_lines_cb(-1)(bufnr) end - local result, err = vim.lsp.buf_request_sync( + local result, _ = vim.lsp.buf_request_sync( 0, vim.lsp.protocol.Methods.textDocument_documentSymbol, { textDocument = vim.lsp.util.make_text_document_params(bufnr) } diff --git a/neovim.toml b/neovim.toml new file mode 100644 index 00000000..9544eea1 --- /dev/null +++ b/neovim.toml @@ -0,0 +1,6 @@ +[selene] +base = "lua51" +name = "neovim" + +[vim] +any = true diff --git a/plugin/vectorcode.lua b/plugin/vectorcode.lua index 0d9d3ccc..ea54bb78 100644 --- a/plugin/vectorcode.lua +++ b/plugin/vectorcode.lua @@ -2,7 +2,7 @@ local vc_config = require("vectorcode.config") local notify_opts = vc_config.notify_opts ---@param args string[]? ----@return {string: any} +---@return table local function process_args(args) if args == nil then return {} @@ -48,7 +48,7 @@ vim.api.nvim_create_user_command("VectorCode", function(args) end end, { nargs = 1, - complete = function(arglead, cmd, cursorpos) + complete = function(arglead, cmd, _) local cacher = vc_config.get_cacher_backend() local splitted_cmd = vim.tbl_filter(function(str) return str ~= nil and str ~= "" diff --git a/selene.toml b/selene.toml new file mode 100644 index 00000000..46a4d1eb --- /dev/null +++ b/selene.toml @@ -0,0 +1,5 @@ +std = "neovim" +exclude = ['lua/vectorcode/integrations/codecompanion/legacy_tool.lua'] + +[rules] +mixed_table = "allow"