mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 21:28:51 +00:00
Allow automatically detect the rustc-src directory (fixes #3517).
If the configured rustcSource is set to "discover", try to automatically detect a source from the sysroot rustc directory.
This commit is contained in:
parent
2967e783ac
commit
4a6e602c94
7 changed files with 67 additions and 20 deletions
|
@ -44,6 +44,15 @@ impl ops::Index<Target> for CargoWorkspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes how to set the rustc source directory.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum RustcSource {
|
||||||
|
/// Explicit path for the rustc source directory.
|
||||||
|
Path(AbsPathBuf),
|
||||||
|
/// Try to automatically detect where the rustc source directory is.
|
||||||
|
Discover,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct CargoConfig {
|
pub struct CargoConfig {
|
||||||
/// Do not activate the `default` feature.
|
/// Do not activate the `default` feature.
|
||||||
|
@ -64,7 +73,7 @@ pub struct CargoConfig {
|
||||||
pub no_sysroot: bool,
|
pub no_sysroot: bool,
|
||||||
|
|
||||||
/// rustc private crate source
|
/// rustc private crate source
|
||||||
pub rustc_source: Option<AbsPathBuf>,
|
pub rustc_source: Option<RustcSource>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Package = Idx<PackageData>;
|
pub type Package = Idx<PackageData>;
|
||||||
|
|
|
@ -21,8 +21,8 @@ use rustc_hash::FxHashSet;
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
build_data::{BuildDataCollector, BuildDataResult},
|
build_data::{BuildDataCollector, BuildDataResult},
|
||||||
cargo_workspace::{
|
cargo_workspace::{
|
||||||
CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, Target, TargetData,
|
CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, RustcSource, Target,
|
||||||
TargetKind,
|
TargetData, TargetKind,
|
||||||
},
|
},
|
||||||
project_json::{ProjectJson, ProjectJsonData},
|
project_json::{ProjectJson, ProjectJsonData},
|
||||||
sysroot::Sysroot,
|
sysroot::Sysroot,
|
||||||
|
|
|
@ -51,11 +51,18 @@ impl Sysroot {
|
||||||
pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
|
pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
|
||||||
log::debug!("Discovering sysroot for {}", cargo_toml.display());
|
log::debug!("Discovering sysroot for {}", cargo_toml.display());
|
||||||
let current_dir = cargo_toml.parent().unwrap();
|
let current_dir = cargo_toml.parent().unwrap();
|
||||||
let sysroot_src_dir = discover_sysroot_src_dir(current_dir)?;
|
let sysroot_dir = discover_sysroot_dir(current_dir)?;
|
||||||
|
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?;
|
||||||
let res = Sysroot::load(&sysroot_src_dir)?;
|
let res = Sysroot::load(&sysroot_src_dir)?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn discover_rustc(cargo_toml: &AbsPath) -> Option<AbsPathBuf> {
|
||||||
|
log::debug!("Discovering rustc source for {}", cargo_toml.display());
|
||||||
|
let current_dir = cargo_toml.parent().unwrap();
|
||||||
|
discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
|
pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
|
||||||
let mut sysroot = Sysroot { crates: Arena::default() };
|
let mut sysroot = Sysroot { crates: Arena::default() };
|
||||||
|
|
||||||
|
@ -110,7 +117,18 @@ impl Sysroot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
|
fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
|
||||||
|
let mut rustc = Command::new(toolchain::rustc());
|
||||||
|
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
|
||||||
|
log::debug!("Discovering sysroot by {:?}", rustc);
|
||||||
|
let stdout = utf8_stdout(rustc)?;
|
||||||
|
Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn discover_sysroot_src_dir(
|
||||||
|
sysroot_path: &AbsPathBuf,
|
||||||
|
current_dir: &AbsPath,
|
||||||
|
) -> Result<AbsPathBuf> {
|
||||||
if let Ok(path) = env::var("RUST_SRC_PATH") {
|
if let Ok(path) = env::var("RUST_SRC_PATH") {
|
||||||
let path = AbsPathBuf::try_from(path.as_str())
|
let path = AbsPathBuf::try_from(path.as_str())
|
||||||
.map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
|
.map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
|
||||||
|
@ -122,14 +140,6 @@ fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
|
||||||
log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
|
log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sysroot_path = {
|
|
||||||
let mut rustc = Command::new(toolchain::rustc());
|
|
||||||
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
|
|
||||||
log::debug!("Discovering sysroot by {:?}", rustc);
|
|
||||||
let stdout = utf8_stdout(rustc)?;
|
|
||||||
AbsPathBuf::assert(PathBuf::from(stdout))
|
|
||||||
};
|
|
||||||
|
|
||||||
get_rust_src(&sysroot_path)
|
get_rust_src(&sysroot_path)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
let mut rustup = Command::new(toolchain::rustup());
|
let mut rustup = Command::new(toolchain::rustup());
|
||||||
|
@ -149,6 +159,16 @@ try installing the Rust source the same way you installed rustc",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_rustc_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
|
||||||
|
let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
|
||||||
|
log::debug!("Checking for rustc source code: {}", rustc_src.display());
|
||||||
|
if rustc_src.exists() {
|
||||||
|
Some(rustc_src)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
|
fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
|
||||||
// Try the new path first since the old one still exists.
|
// Try the new path first since the old one still exists.
|
||||||
let rust_src = sysroot_path.join("lib/rustlib/src/rust");
|
let rust_src = sysroot_path.join("lib/rustlib/src/rust");
|
||||||
|
|
|
@ -114,6 +114,7 @@ impl ProjectWorkspace {
|
||||||
cargo_version
|
cargo_version
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let sysroot = if config.no_sysroot {
|
let sysroot = if config.no_sysroot {
|
||||||
Sysroot::default()
|
Sysroot::default()
|
||||||
} else {
|
} else {
|
||||||
|
@ -125,7 +126,17 @@ impl ProjectWorkspace {
|
||||||
})?
|
})?
|
||||||
};
|
};
|
||||||
|
|
||||||
let rustc = if let Some(rustc_dir) = &config.rustc_source {
|
let rustc_dir = if let Some(rustc_source) = &config.rustc_source {
|
||||||
|
use cargo_workspace::RustcSource;
|
||||||
|
match rustc_source {
|
||||||
|
RustcSource::Path(path) => Some(path.clone()),
|
||||||
|
RustcSource::Discover => Sysroot::discover_rustc(&cargo_toml),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let rustc = if let Some(rustc_dir) = rustc_dir {
|
||||||
Some(
|
Some(
|
||||||
CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress)
|
CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress)
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
|
|
|
@ -18,7 +18,7 @@ use ide_db::helpers::{
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lsp_types::{ClientCapabilities, MarkupKind};
|
use lsp_types::{ClientCapabilities, MarkupKind};
|
||||||
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
|
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use serde::{de::DeserializeOwned, Deserialize};
|
use serde::{de::DeserializeOwned, Deserialize};
|
||||||
use vfs::AbsPathBuf;
|
use vfs::AbsPathBuf;
|
||||||
|
@ -177,8 +177,9 @@ config_data! {
|
||||||
/// tests or binaries.\nFor example, it may be `--release`.
|
/// tests or binaries.\nFor example, it may be `--release`.
|
||||||
runnables_cargoExtraArgs: Vec<String> = "[]",
|
runnables_cargoExtraArgs: Vec<String> = "[]",
|
||||||
|
|
||||||
/// Path to the rust compiler sources, for usage in rustc_private projects.
|
/// Path to the rust compiler sources, for usage in rustc_private projects, or "discover"
|
||||||
rustcSource : Option<PathBuf> = "null",
|
/// to try to automatically find it.
|
||||||
|
rustcSource : Option<String> = "null",
|
||||||
|
|
||||||
/// Additional arguments to `rustfmt`.
|
/// Additional arguments to `rustfmt`.
|
||||||
rustfmt_extraArgs: Vec<String> = "[]",
|
rustfmt_extraArgs: Vec<String> = "[]",
|
||||||
|
@ -473,7 +474,13 @@ impl Config {
|
||||||
self.data.cargo_loadOutDirsFromCheck
|
self.data.cargo_loadOutDirsFromCheck
|
||||||
}
|
}
|
||||||
pub fn cargo(&self) -> CargoConfig {
|
pub fn cargo(&self) -> CargoConfig {
|
||||||
let rustc_source = self.data.rustcSource.as_ref().map(|it| self.root_path.join(&it));
|
let rustc_source = self.data.rustcSource.as_ref().map(|rustc_src| {
|
||||||
|
if rustc_src == "discover" {
|
||||||
|
RustcSource::Discover
|
||||||
|
} else {
|
||||||
|
RustcSource::Path(self.root_path.join(rustc_src))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
CargoConfig {
|
CargoConfig {
|
||||||
no_default_features: self.data.cargo_noDefaultFeatures,
|
no_default_features: self.data.cargo_noDefaultFeatures,
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
[[rust-analyzer.runnables.cargoExtraArgs]]rust-analyzer.runnables.cargoExtraArgs (default: `[]`)::
|
[[rust-analyzer.runnables.cargoExtraArgs]]rust-analyzer.runnables.cargoExtraArgs (default: `[]`)::
|
||||||
Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`.
|
Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`.
|
||||||
[[rust-analyzer.rustcSource]]rust-analyzer.rustcSource (default: `null`)::
|
[[rust-analyzer.rustcSource]]rust-analyzer.rustcSource (default: `null`)::
|
||||||
Path to the rust compiler sources, for usage in rustc_private projects.
|
Path to the rust compiler sources, for usage in rustc_private projects, or "discover" to try to automatically find it.
|
||||||
[[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`)::
|
[[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`)::
|
||||||
Additional arguments to `rustfmt`.
|
Additional arguments to `rustfmt`.
|
||||||
[[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`)::
|
[[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`)::
|
||||||
|
|
|
@ -707,7 +707,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rust-analyzer.rustcSource": {
|
"rust-analyzer.rustcSource": {
|
||||||
"markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects.",
|
"markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects, or \"discover\" to try to automatically find it.",
|
||||||
"default": null,
|
"default": null,
|
||||||
"type": [
|
"type": [
|
||||||
"null",
|
"null",
|
||||||
|
|
Loading…
Reference in a new issue