Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 49 additions & 43 deletions lua/rustaceanvim/cargo.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,92 +29,98 @@ end
---client root is found, returns the result of evaluating `config.root_dir`.
---@param config rustaceanvim.lsp.ClientConfig
---@param file_name string
---@return string | nil root_dir
function cargo.get_config_root_dir(config, file_name)
---@param callback fun(root_dir: string?)
function cargo.get_config_root_dir(config, file_name, callback)
local reuse_active = get_mb_active_client_root(file_name)
if reuse_active then
return reuse_active
return callback(reuse_active)
end

local config_root_dir = config.root_dir
if type(config_root_dir) == 'function' then
return config_root_dir(file_name, cargo.get_root_dir)
config_root_dir(file_name, callback, function(file_name_)
cargo.get_root_dir(file_name_, callback)
end)
else
return config_root_dir
callback(config_root_dir)
end
end

---@param path string The directory to search upward from
---@return string? cargo_crate_dir
---@return table? cargo_metadata
local function get_cargo_metadata(path)
---@param callback fun(cargo_crate_dir: string?, cargo_metadata: table?)
local function get_cargo_metadata(path, callback)
---@diagnostic disable-next-line: missing-fields
local cargo_crate_dir = vim.fs.dirname(vim.fs.find({ 'Cargo.toml' }, {
upward = true,
path = path,
})[1])
if vim.fn.executable('cargo') ~= 1 then
return cargo_crate_dir
return callback(cargo_crate_dir)
end
local cmd = { 'cargo', 'metadata', '--no-deps', '--format-version', '1' }
if cargo_crate_dir ~= nil then
cmd[#cmd + 1] = '--manifest-path'
cmd[#cmd + 1] = vim.fs.joinpath(cargo_crate_dir, 'Cargo.toml')
end
local sc = vim
.system(cmd, {
cwd = vim.uv.fs_stat(path) and path or cargo_crate_dir or vim.fn.getcwd(),
})
:wait()
if sc.code ~= 0 then
return cargo_crate_dir
end
local ok, cargo_metadata_json = pcall(vim.fn.json_decode, sc.stdout)
if ok and cargo_metadata_json then
return cargo_crate_dir, cargo_metadata_json
end
return cargo_crate_dir
vim.uv.fs_stat(path, function(_, stat)
vim.system(cmd, {
cwd = stat and path or cargo_crate_dir or vim.fn.getcwd(),
}, function(sc)
if sc.code ~= 0 then
return callback(cargo_crate_dir)
end
local ok, cargo_metadata_json = pcall(vim.fn.json_decode, sc.stdout)
if ok and cargo_metadata_json then
return callback(cargo_crate_dir, cargo_metadata_json)
end
return callback(cargo_crate_dir)
end)
end)
end

---@param buf_name? string
---@return string edition
function cargo.get_rustc_edition(buf_name)
---@param callback fun(edition: string)
function cargo.get_rustc_edition(buf_name, callback)
local config = require('rustaceanvim.config.internal')
---@diagnostic disable-next-line: undefined-field
if config.tools.rustc.edition then
vim.deprecate('vim.g.rustaceanvim.config.tools.edition', 'default_edition', '6.0.0', 'rustaceanvim')
---@diagnostic disable-next-line: undefined-field
return config.tools.rustc.edition
callback(config.tools.rustc.edition)
end
buf_name = buf_name or vim.api.nvim_buf_get_name(0)
local path = vim.fs.dirname(buf_name)
local _, cargo_metadata = get_cargo_metadata(path)
local default_edition = config.tools.rustc.default_edition
if not cargo_metadata then
return default_edition
end
local package = vim.iter(cargo_metadata.packages or {}):find(function(pkg)
return type(pkg.edition) == 'string'
get_cargo_metadata(path, function(_, cargo_metadata)
local default_edition = config.tools.rustc.default_edition
if not cargo_metadata then
return callback(default_edition)
end
local package = vim.iter(cargo_metadata.packages or {}):find(function(pkg)
return type(pkg.edition) == 'string'
end)
callback(package and package.edition or default_edition)
end)
return package and package.edition or default_edition
end

---The default implementation used for `vim.g.rustaceanvim.server.root_dir`
---@param file_name string
---@return string | nil root_dir
function cargo.get_root_dir(file_name)
---@param callback fun(root_dir: string | nil)
function cargo.get_root_dir(file_name, callback)
local path = file_name:find('%.rs$') and vim.fs.dirname(file_name) or file_name
if not path then
return nil
end
local cargo_crate_dir, cargo_metadata = get_cargo_metadata(path)
return cargo_metadata and cargo_metadata.workspace_root
or cargo_crate_dir
---@diagnostic disable-next-line: missing-fields
or vim.fs.dirname(vim.fs.find({ 'rust-project.json' }, {
upward = true,
path = path,
})[1])
get_cargo_metadata(path, function(cargo_crate_dir, cargo_metadata)
callback(
cargo_metadata and cargo_metadata.workspace_root
or cargo_crate_dir
---@diagnostic disable-next-line: missing-fields
or vim.fs.dirname(vim.fs.find({ 'rust-project.json' }, {
upward = true,
path = path,
})[1])
)
end)
end

return cargo
26 changes: 14 additions & 12 deletions lua/rustaceanvim/commands/rustc_unpretty.lua
Original file line number Diff line number Diff line change
Expand Up @@ -135,18 +135,20 @@ function M.rustc_unpretty(level)
end
text = table.concat(b, '\n')

vim.system({
rustc,
'--crate-type',
'lib',
'--edition',
cargo.get_rustc_edition(),
'-Z',
'unstable-options',
'-Z',
'unpretty=' .. level,
'-',
}, { stdin = text }, vim.schedule_wrap(handler))
cargo.get_rustc_edition(nil, function(edition)
vim.system({
rustc,
'--crate-type',
'lib',
'--edition',
edition,
'-Z',
'unstable-options',
'-Z',
'unpretty=' .. level,
'-',
}, { stdin = text }, vim.schedule_wrap(handler))
end)
end

return M
2 changes: 1 addition & 1 deletion lua/rustaceanvim/config/internal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ local RustaceanDefaultConfig = {
return { 'rust-analyzer', '--log-file', RustaceanConfig.server.logfile }
end,

---@type string | fun(filename: string, default: fun(filename: string):string|nil):string|nil
---@type string | fun(filename: string, callback: fun(root_dir: string|nil), default: fun(filename: string):string|nil)
root_dir = cargo.get_root_dir,

ra_multiplex = {
Expand Down
Loading