From 0685a3a39fbc13f6b06ee38516a18ea62075c97b Mon Sep 17 00:00:00 2001 From: Fredrik Averpil Date: Fri, 3 Jan 2025 16:30:26 +0100 Subject: [PATCH] perf: use nio.process.run instead of vim.system This should avoid having Neovim freeze during long-running 'go list' command. Co-authored-by: Bruno Mazzo --- lua/neotest-golang/lib/cmd.lua | 49 +++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/lua/neotest-golang/lib/cmd.lua b/lua/neotest-golang/lib/cmd.lua index 7ab8fd85..6e1df784 100644 --- a/lua/neotest-golang/lib/cmd.lua +++ b/lua/neotest-golang/lib/cmd.lua @@ -15,25 +15,50 @@ function M.golist_data(cwd) local cmd = M.golist_command() local go_list_command_concat = table.concat(cmd, " ") logger.info("Running Go list: " .. go_list_command_concat .. " in " .. cwd) - local result = vim.system(cmd, { cwd = cwd, text = true }):wait() + -- local result = vim.system(cmd, { cwd = cwd, text = true }):wait() + local bin = table.remove(cmd, 1) -- removes "go" from cmd + local args = cmd - local err = nil - if result.code == 1 then - err = "go list:" - if result.stdout ~= nil and result.stdout ~= "" then - err = err .. " " .. result.stdout + local process, err = async.process.run({ cmd = bin, args = args, cwd = cwd }) + if not process then + return nil, string.format("Failed to start go list: %s", err) + end + + local output, output_err = process.stdout.read() + local error_out, error_err = process.stderr.read() + + -- Get result and auto-close the process + local command_return_code = process.result(true) + + -- Handle stream reading errors + if output_err then + return nil, string.format("Failed to read stdout: %s", output_err) + end + if error_err then + return nil, string.format("Failed to read stderr: %s", error_err) + end + + -- Handle command execution errors + if command_return_code == 1 then + local err_msg = "go list:" + if output and output ~= "" then + err_msg = err_msg .. " " .. output end - if result.stdout ~= nil and result.stderr ~= "" then - err = err .. " " .. result.stderr + if error_out and error_out ~= "" then + err_msg = err_msg .. " " .. error_out end - logger.warn({ "Go list error: ", err }) + logger.warn({ "Go list error: ", err_msg }) + return nil, err_msg end - local output = result.stdout or "" + -- Parse JSON output + local ok, golist_output = pcall(json.decode_from_string, output or "") + if not ok then + return nil, string.format("Failed to parse JSON output: %s", golist_output) + end - local golist_output = json.decode_from_string(output) logger.debug({ "JSON-decoded 'go list' output: ", golist_output }) - return golist_output, err + return golist_output, nil end function M.golist_command()