/// Roots and crates that compose this Rust project.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ProjectJson {
+ /// e.g. `path/to/sysroot`
+ pub(crate) sysroot: Option<AbsPathBuf>,
+ /// e.g. `path/to/sysroot/lib/rustlib/src/rust`
pub(crate) sysroot_src: Option<AbsPathBuf>,
project_root: AbsPathBuf,
crates: Vec<Crate>,
/// configuration.
pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson {
ProjectJson {
+ sysroot: data.sysroot.map(|it| base.join(it)),
sysroot_src: data.sysroot_src.map(|it| base.join(it)),
project_root: base.to_path_buf(),
crates: data
#[derive(Deserialize, Debug, Clone)]
pub struct ProjectJsonData {
+ sysroot: Option<PathBuf>,
sysroot_src: Option<PathBuf>,
crates: Vec<CrateData>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Sysroot {
root: AbsPathBuf,
+ src_root: AbsPathBuf,
crates: Arena<SysrootCrateData>,
}
}
impl Sysroot {
+ /// Returns sysroot directory, where `bin/`, `etc/`, `lib/`, `libexec/`
+ /// subfolder live, like:
+ /// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library`
+ pub fn src_root(&self) -> &AbsPath {
+ &self.src_root
+ }
+
+ /// Returns sysroot "src" directory, where stdlib sources are located, like:
+ /// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu`
pub fn root(&self) -> &AbsPath {
&self.root
}
tracing::debug!("Discovering sysroot for {}", dir.display());
let sysroot_dir = discover_sysroot_dir(dir)?;
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir)?;
- let res = Sysroot::load(sysroot_src_dir)?;
+ let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
Ok(res)
}
discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
}
- pub fn load(sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
- let mut sysroot = Sysroot { root: sysroot_src_dir, crates: Arena::default() };
+ pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
+ let mut sysroot =
+ Sysroot { root: sysroot_dir, src_root: sysroot_src_dir, crates: Arena::default() };
for path in SYSROOT_CRATES.trim().lines() {
let name = path.split('/').last().unwrap();
let root = [format!("{}/src/lib.rs", path), format!("lib{}/lib.rs", path)]
.into_iter()
- .map(|it| sysroot.root.join(it))
+ .map(|it| sysroot.src_root.join(it))
.filter_map(|it| ManifestPath::try_from(it).ok())
.find(|it| fs::metadata(it).is_ok());
};
anyhow::bail!(
"could not find libcore in sysroot path `{}`{}",
- sysroot.root.as_path().display(),
+ sysroot.src_root.as_path().display(),
var_note,
);
}
fn get_fake_sysroot() -> Sysroot {
let sysroot_path = get_test_path("fake-sysroot");
- let sysroot_src_dir = AbsPathBuf::assert(sysroot_path);
- Sysroot::load(sysroot_src_dir).unwrap()
+ // there's no `libexec/` directory with a `proc-macro-srv` binary in that
+ // fake sysroot, so we give them both the same path:
+ let sysroot_dir = AbsPathBuf::assert(sysroot_path);
+ let sysroot_src_dir = sysroot_dir.clone();
+ Sysroot::load(sysroot_dir, sysroot_src_dir).unwrap()
}
fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
project_json: ProjectJson,
target: Option<&str>,
) -> Result<ProjectWorkspace> {
- let sysroot = match &project_json.sysroot_src {
- Some(path) => Some(Sysroot::load(path.clone())?),
+ let sysroot = match project_json.sysroot_src.clone() {
+ Some(sysroot_src) => {
+ // if `sysroot` isn't specified (only `sysroot_src`), we won't have
+ // a real sysroot path, that's fine. it's just used to discover
+ // the standalone `proc-macro-srv` binary.
+ let sysroot = project_json.sysroot.clone().unwrap_or_else(|| sysroot_src.clone());
+ Some(Sysroot::load(sysroot, sysroot_src)?)
+ }
None => None,
};
let rustc_cfg = rustc_cfg::get(None, target);
})
.chain(sysroot.iter().map(|sysroot| PackageRoot {
is_local: false,
- include: vec![sysroot.root().to_path_buf()],
+ include: vec![sysroot.src_root().to_path_buf()],
exclude: Vec::new(),
}))
.chain(rustc.iter().flat_map(|rustc| {
if self.proc_macro_clients.is_empty() {
if let Some((path, args)) = self.config.proc_macro_srv() {
- self.proc_macro_clients = (0..self.workspaces.len())
- .map(|_| {
+ self.proc_macro_clients = self
+ .workspaces
+ .iter()
+ .map(|ws| {
+ let mut path = path.clone();
+ if let ProjectWorkspace::Cargo { sysroot, .. } = ws {
+ tracing::info!("Found a cargo workspace...");
+ if let Some(sysroot) = sysroot.as_ref() {
+ tracing::info!("Found a cargo workspace with a sysroot...");
+ let server_path = sysroot
+ .root()
+ .join("libexec")
+ .join("rust-analyzer-proc-macro-srv");
+ if std::fs::metadata(&server_path).is_ok() {
+ tracing::info!(
+ "And the server exists at {}",
+ server_path.display()
+ );
+ path = server_path;
+ } else {
+ tracing::info!(
+ "And the server does not exist at {}",
+ server_path.display()
+ );
+ }
+ }
+ }
+
ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
let error = format!(
"Failed to run proc_macro_srv from path {}, error: {:?}",