diff options
author | Benjamin Bouvier <[email protected]> | 2021-02-11 16:34:56 +0000 |
---|---|---|
committer | Benjamin Bouvier <[email protected]> | 2021-02-13 17:20:46 +0000 |
commit | 4a6e602c9419cc5ed464343b2373c7fe86fb89d6 (patch) | |
tree | ed4148a4ccb0a7e81cb897f611e66e40bf492488 | |
parent | 2967e783ac53e89f06a8f8bd1afc12433311fded (diff) |
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.
-rw-r--r-- | crates/project_model/src/cargo_workspace.rs | 11 | ||||
-rw-r--r-- | crates/project_model/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/project_model/src/sysroot.rs | 40 | ||||
-rw-r--r-- | crates/project_model/src/workspace.rs | 13 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 15 | ||||
-rw-r--r-- | docs/user/generated_config.adoc | 2 | ||||
-rw-r--r-- | editors/code/package.json | 2 |
7 files changed, 67 insertions, 20 deletions
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index f47898b9b..1d8d34a0b 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs | |||
@@ -44,6 +44,15 @@ impl ops::Index<Target> for CargoWorkspace { | |||
44 | } | 44 | } |
45 | } | 45 | } |
46 | 46 | ||
47 | /// Describes how to set the rustc source directory. | ||
48 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
49 | pub enum RustcSource { | ||
50 | /// Explicit path for the rustc source directory. | ||
51 | Path(AbsPathBuf), | ||
52 | /// Try to automatically detect where the rustc source directory is. | ||
53 | Discover, | ||
54 | } | ||
55 | |||
47 | #[derive(Default, Clone, Debug, PartialEq, Eq)] | 56 | #[derive(Default, Clone, Debug, PartialEq, Eq)] |
48 | pub struct CargoConfig { | 57 | pub struct CargoConfig { |
49 | /// Do not activate the `default` feature. | 58 | /// Do not activate the `default` feature. |
@@ -64,7 +73,7 @@ pub struct CargoConfig { | |||
64 | pub no_sysroot: bool, | 73 | pub no_sysroot: bool, |
65 | 74 | ||
66 | /// rustc private crate source | 75 | /// rustc private crate source |
67 | pub rustc_source: Option<AbsPathBuf>, | 76 | pub rustc_source: Option<RustcSource>, |
68 | } | 77 | } |
69 | 78 | ||
70 | pub type Package = Idx<PackageData>; | 79 | pub type Package = Idx<PackageData>; |
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index d712095a6..a5b35ed95 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs | |||
@@ -21,8 +21,8 @@ use rustc_hash::FxHashSet; | |||
21 | pub use crate::{ | 21 | pub use crate::{ |
22 | build_data::{BuildDataCollector, BuildDataResult}, | 22 | build_data::{BuildDataCollector, BuildDataResult}, |
23 | cargo_workspace::{ | 23 | cargo_workspace::{ |
24 | CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, Target, TargetData, | 24 | CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, RustcSource, Target, |
25 | TargetKind, | 25 | TargetData, TargetKind, |
26 | }, | 26 | }, |
27 | project_json::{ProjectJson, ProjectJsonData}, | 27 | project_json::{ProjectJson, ProjectJsonData}, |
28 | sysroot::Sysroot, | 28 | sysroot::Sysroot, |
diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs index ff44dae4a..3b0ff506d 100644 --- a/crates/project_model/src/sysroot.rs +++ b/crates/project_model/src/sysroot.rs | |||
@@ -51,11 +51,18 @@ impl Sysroot { | |||
51 | pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> { | 51 | pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> { |
52 | log::debug!("Discovering sysroot for {}", cargo_toml.display()); | 52 | log::debug!("Discovering sysroot for {}", cargo_toml.display()); |
53 | let current_dir = cargo_toml.parent().unwrap(); | 53 | let current_dir = cargo_toml.parent().unwrap(); |
54 | let sysroot_src_dir = discover_sysroot_src_dir(current_dir)?; | 54 | let sysroot_dir = discover_sysroot_dir(current_dir)?; |
55 | let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?; | ||
55 | let res = Sysroot::load(&sysroot_src_dir)?; | 56 | let res = Sysroot::load(&sysroot_src_dir)?; |
56 | Ok(res) | 57 | Ok(res) |
57 | } | 58 | } |
58 | 59 | ||
60 | pub fn discover_rustc(cargo_toml: &AbsPath) -> Option<AbsPathBuf> { | ||
61 | log::debug!("Discovering rustc source for {}", cargo_toml.display()); | ||
62 | let current_dir = cargo_toml.parent().unwrap(); | ||
63 | discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir)) | ||
64 | } | ||
65 | |||
59 | pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> { | 66 | pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> { |
60 | let mut sysroot = Sysroot { crates: Arena::default() }; | 67 | let mut sysroot = Sysroot { crates: Arena::default() }; |
61 | 68 | ||
@@ -110,7 +117,18 @@ impl Sysroot { | |||
110 | } | 117 | } |
111 | } | 118 | } |
112 | 119 | ||
113 | fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> { | 120 | fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> { |
121 | let mut rustc = Command::new(toolchain::rustc()); | ||
122 | rustc.current_dir(current_dir).args(&["--print", "sysroot"]); | ||
123 | log::debug!("Discovering sysroot by {:?}", rustc); | ||
124 | let stdout = utf8_stdout(rustc)?; | ||
125 | Ok(AbsPathBuf::assert(PathBuf::from(stdout))) | ||
126 | } | ||
127 | |||
128 | fn discover_sysroot_src_dir( | ||
129 | sysroot_path: &AbsPathBuf, | ||
130 | current_dir: &AbsPath, | ||
131 | ) -> Result<AbsPathBuf> { | ||
114 | if let Ok(path) = env::var("RUST_SRC_PATH") { | 132 | if let Ok(path) = env::var("RUST_SRC_PATH") { |
115 | let path = AbsPathBuf::try_from(path.as_str()) | 133 | let path = AbsPathBuf::try_from(path.as_str()) |
116 | .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?; | 134 | .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> { | |||
122 | log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core); | 140 | log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core); |
123 | } | 141 | } |
124 | 142 | ||
125 | let sysroot_path = { | ||
126 | let mut rustc = Command::new(toolchain::rustc()); | ||
127 | rustc.current_dir(current_dir).args(&["--print", "sysroot"]); | ||
128 | log::debug!("Discovering sysroot by {:?}", rustc); | ||
129 | let stdout = utf8_stdout(rustc)?; | ||
130 | AbsPathBuf::assert(PathBuf::from(stdout)) | ||
131 | }; | ||
132 | |||
133 | get_rust_src(&sysroot_path) | 143 | get_rust_src(&sysroot_path) |
134 | .or_else(|| { | 144 | .or_else(|| { |
135 | let mut rustup = Command::new(toolchain::rustup()); | 145 | let mut rustup = Command::new(toolchain::rustup()); |
@@ -149,6 +159,16 @@ try installing the Rust source the same way you installed rustc", | |||
149 | }) | 159 | }) |
150 | } | 160 | } |
151 | 161 | ||
162 | fn get_rustc_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> { | ||
163 | let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml"); | ||
164 | log::debug!("Checking for rustc source code: {}", rustc_src.display()); | ||
165 | if rustc_src.exists() { | ||
166 | Some(rustc_src) | ||
167 | } else { | ||
168 | None | ||
169 | } | ||
170 | } | ||
171 | |||
152 | fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> { | 172 | fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> { |
153 | // Try the new path first since the old one still exists. | 173 | // Try the new path first since the old one still exists. |
154 | let rust_src = sysroot_path.join("lib/rustlib/src/rust"); | 174 | let rust_src = sysroot_path.join("lib/rustlib/src/rust"); |
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index c30861976..0220efdb4 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -114,6 +114,7 @@ impl ProjectWorkspace { | |||
114 | cargo_version | 114 | cargo_version |
115 | ) | 115 | ) |
116 | })?; | 116 | })?; |
117 | |||
117 | let sysroot = if config.no_sysroot { | 118 | let sysroot = if config.no_sysroot { |
118 | Sysroot::default() | 119 | Sysroot::default() |
119 | } else { | 120 | } else { |
@@ -125,7 +126,17 @@ impl ProjectWorkspace { | |||
125 | })? | 126 | })? |
126 | }; | 127 | }; |
127 | 128 | ||
128 | let rustc = if let Some(rustc_dir) = &config.rustc_source { | 129 | let rustc_dir = if let Some(rustc_source) = &config.rustc_source { |
130 | use cargo_workspace::RustcSource; | ||
131 | match rustc_source { | ||
132 | RustcSource::Path(path) => Some(path.clone()), | ||
133 | RustcSource::Discover => Sysroot::discover_rustc(&cargo_toml), | ||
134 | } | ||
135 | } else { | ||
136 | None | ||
137 | }; | ||
138 | |||
139 | let rustc = if let Some(rustc_dir) = rustc_dir { | ||
129 | Some( | 140 | Some( |
130 | CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress) | 141 | CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress) |
131 | .with_context(|| { | 142 | .with_context(|| { |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index cc0b22bff..f9098968a 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -18,7 +18,7 @@ use ide_db::helpers::{ | |||
18 | }; | 18 | }; |
19 | use itertools::Itertools; | 19 | use itertools::Itertools; |
20 | use lsp_types::{ClientCapabilities, MarkupKind}; | 20 | use lsp_types::{ClientCapabilities, MarkupKind}; |
21 | use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; | 21 | use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource}; |
22 | use rustc_hash::FxHashSet; | 22 | use rustc_hash::FxHashSet; |
23 | use serde::{de::DeserializeOwned, Deserialize}; | 23 | use serde::{de::DeserializeOwned, Deserialize}; |
24 | use vfs::AbsPathBuf; | 24 | use vfs::AbsPathBuf; |
@@ -177,8 +177,9 @@ config_data! { | |||
177 | /// tests or binaries.\nFor example, it may be `--release`. | 177 | /// tests or binaries.\nFor example, it may be `--release`. |
178 | runnables_cargoExtraArgs: Vec<String> = "[]", | 178 | runnables_cargoExtraArgs: Vec<String> = "[]", |
179 | 179 | ||
180 | /// Path to the rust compiler sources, for usage in rustc_private projects. | 180 | /// Path to the rust compiler sources, for usage in rustc_private projects, or "discover" |
181 | rustcSource : Option<PathBuf> = "null", | 181 | /// to try to automatically find it. |
182 | rustcSource : Option<String> = "null", | ||
182 | 183 | ||
183 | /// Additional arguments to `rustfmt`. | 184 | /// Additional arguments to `rustfmt`. |
184 | rustfmt_extraArgs: Vec<String> = "[]", | 185 | rustfmt_extraArgs: Vec<String> = "[]", |
@@ -473,7 +474,13 @@ impl Config { | |||
473 | self.data.cargo_loadOutDirsFromCheck | 474 | self.data.cargo_loadOutDirsFromCheck |
474 | } | 475 | } |
475 | pub fn cargo(&self) -> CargoConfig { | 476 | pub fn cargo(&self) -> CargoConfig { |
476 | let rustc_source = self.data.rustcSource.as_ref().map(|it| self.root_path.join(&it)); | 477 | let rustc_source = self.data.rustcSource.as_ref().map(|rustc_src| { |
478 | if rustc_src == "discover" { | ||
479 | RustcSource::Discover | ||
480 | } else { | ||
481 | RustcSource::Path(self.root_path.join(rustc_src)) | ||
482 | } | ||
483 | }); | ||
477 | 484 | ||
478 | CargoConfig { | 485 | CargoConfig { |
479 | no_default_features: self.data.cargo_noDefaultFeatures, | 486 | no_default_features: self.data.cargo_noDefaultFeatures, |
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 55178c84c..f91e04c31 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc | |||
@@ -105,7 +105,7 @@ | |||
105 | [[rust-analyzer.runnables.cargoExtraArgs]]rust-analyzer.runnables.cargoExtraArgs (default: `[]`):: | 105 | [[rust-analyzer.runnables.cargoExtraArgs]]rust-analyzer.runnables.cargoExtraArgs (default: `[]`):: |
106 | Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`. | 106 | Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`. |
107 | [[rust-analyzer.rustcSource]]rust-analyzer.rustcSource (default: `null`):: | 107 | [[rust-analyzer.rustcSource]]rust-analyzer.rustcSource (default: `null`):: |
108 | Path to the rust compiler sources, for usage in rustc_private projects. | 108 | Path to the rust compiler sources, for usage in rustc_private projects, or "discover" to try to automatically find it. |
109 | [[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`):: | 109 | [[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`):: |
110 | Additional arguments to `rustfmt`. | 110 | Additional arguments to `rustfmt`. |
111 | [[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`):: | 111 | [[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`):: |
diff --git a/editors/code/package.json b/editors/code/package.json index 55825456e..defa108cb 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -707,7 +707,7 @@ | |||
707 | } | 707 | } |
708 | }, | 708 | }, |
709 | "rust-analyzer.rustcSource": { | 709 | "rust-analyzer.rustcSource": { |
710 | "markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects.", | 710 | "markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects, or \"discover\" to try to automatically find it.", |
711 | "default": null, | 711 | "default": null, |
712 | "type": [ | 712 | "type": [ |
713 | "null", | 713 | "null", |