From 4f3e59770659c09be1921397ebecd7f384af832f Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Thu, 9 Sep 2021 22:17:41 -0400 Subject: fix(rust-analyzer): skip stderr for cargo metadata (#1235) Vim's `system` output includes both STDOUT and STDERR, which means it may contain all sorts of debug output, especially if the user is using custom rustup toolchains. This change ignores STDERR output for parsing the metadata output to fix rust_analyzer in those contexts. This change also moves to `jobstart`/`jobwait` over `system`, which avoids pitfalls related to shell argument parsing and escaping, and allows finer-grained control over output redirection. --- lua/lspconfig/rust_analyzer.lua | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'lua/lspconfig/rust_analyzer.lua') diff --git a/lua/lspconfig/rust_analyzer.lua b/lua/lspconfig/rust_analyzer.lua index 9ff8907f..1f47dc2b 100644 --- a/lua/lspconfig/rust_analyzer.lua +++ b/lua/lspconfig/rust_analyzer.lua @@ -18,14 +18,36 @@ configs.rust_analyzer = { filetypes = { 'rust' }, root_dir = function(fname) local cargo_crate_dir = util.root_pattern 'Cargo.toml'(fname) - local cmd = 'cargo metadata --no-deps --format-version 1' + local cmd = { 'cargo', 'metadata', '--no-deps', '--format-version', '1' } if cargo_crate_dir ~= nil then - cmd = cmd .. ' --manifest-path ' .. util.path.join(cargo_crate_dir, 'Cargo.toml') + cmd[#cmd + 1] = '--manifest-path' + cmd[#cmd + 1] = util.path.join(cargo_crate_dir, 'Cargo.toml') + end + local cargo_metadata = '' + local cargo_metadata_err = '' + local cm = vim.fn.jobstart(cmd, { + on_stdout = function(j, d, e) + cargo_metadata = table.concat(d, '\n') + end, + on_stderr = function(j, d, e) + cargo_metadata_err = table.concat(d, '\n') + end, + stdout_buffered = true, + stderr_buffered = true, + }) + if cm > 0 then + cm = vim.fn.jobwait({ cm })[1] + else + cm = -1 end - local cargo_metadata = vim.fn.system(cmd) local cargo_workspace_dir = nil - if vim.v.shell_error == 0 then + if cm == 0 then cargo_workspace_dir = vim.fn.json_decode(cargo_metadata)['workspace_root'] + else + vim.notify( + string.format('cmd [%q] failed:\n%s', table.concat(cmd, ' '), cargo_metadata_err), + vim.log.levels.Warning + ) end return cargo_workspace_dir or cargo_crate_dir -- cgit v1.2.3-70-g09d2