diff options
Diffstat (limited to 'crates/ra_lsp_server/src/project_model.rs')
-rw-r--r-- | crates/ra_lsp_server/src/project_model.rs | 116 |
1 files changed, 101 insertions, 15 deletions
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs index 9f429c9a1..6fbaba7d9 100644 --- a/crates/ra_lsp_server/src/project_model.rs +++ b/crates/ra_lsp_server/src/project_model.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | use std::path::{Path, PathBuf}; | 1 | use std::{ |
2 | path::{Path, PathBuf}, | ||
3 | process::Command, | ||
4 | }; | ||
2 | 5 | ||
3 | use cargo_metadata::{metadata_run, CargoOpt}; | 6 | use cargo_metadata::{metadata_run, CargoOpt}; |
4 | use ra_syntax::SmolStr; | 7 | use ra_syntax::SmolStr; |
@@ -9,6 +12,36 @@ use thread_worker::{WorkerHandle, Worker}; | |||
9 | 12 | ||
10 | use crate::Result; | 13 | use crate::Result; |
11 | 14 | ||
15 | #[derive(Debug, Clone)] | ||
16 | pub struct ProjectWorkspace { | ||
17 | pub(crate) cargo: CargoWorkspace, | ||
18 | pub(crate) sysroot: Sysroot, | ||
19 | } | ||
20 | |||
21 | impl ProjectWorkspace { | ||
22 | pub fn discover(path: &Path) -> Result<ProjectWorkspace> { | ||
23 | let cargo_toml = find_cargo_toml(path)?; | ||
24 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml)?; | ||
25 | let sysroot = sysroot_info(&cargo_toml)?; | ||
26 | let res = ProjectWorkspace { cargo, sysroot }; | ||
27 | Ok(res) | ||
28 | } | ||
29 | } | ||
30 | |||
31 | pub fn workspace_loader() -> (Worker<PathBuf, Result<ProjectWorkspace>>, WorkerHandle) { | ||
32 | thread_worker::spawn::<PathBuf, Result<ProjectWorkspace>, _>( | ||
33 | "workspace loader", | ||
34 | 1, | ||
35 | |input_receiver, output_sender| { | ||
36 | input_receiver | ||
37 | .into_iter() | ||
38 | .map(|path| ProjectWorkspace::discover(path.as_path())) | ||
39 | .try_for_each(|it| output_sender.send(it)) | ||
40 | .unwrap() | ||
41 | }, | ||
42 | ) | ||
43 | } | ||
44 | |||
12 | /// `CargoWorksapce` represents the logical structure of, well, a Cargo | 45 | /// `CargoWorksapce` represents the logical structure of, well, a Cargo |
13 | /// workspace. It pretty closely mirrors `cargo metadata` output. | 46 | /// workspace. It pretty closely mirrors `cargo metadata` output. |
14 | /// | 47 | /// |
@@ -63,6 +96,11 @@ pub enum TargetKind { | |||
63 | Other, | 96 | Other, |
64 | } | 97 | } |
65 | 98 | ||
99 | #[derive(Debug, Clone)] | ||
100 | pub(crate) struct Sysroot { | ||
101 | crates: FxHashMap<SmolStr, PathBuf>, | ||
102 | } | ||
103 | |||
66 | impl Package { | 104 | impl Package { |
67 | pub fn name(self, ws: &CargoWorkspace) -> &str { | 105 | pub fn name(self, ws: &CargoWorkspace) -> &str { |
68 | ws.packages[self].name.as_str() | 106 | ws.packages[self].name.as_str() |
@@ -160,6 +198,68 @@ impl CargoWorkspace { | |||
160 | } | 198 | } |
161 | } | 199 | } |
162 | 200 | ||
201 | fn sysroot_info(cargo_toml: &Path) -> Result<Sysroot> { | ||
202 | let rustc_output = Command::new("rustc") | ||
203 | .current_dir(cargo_toml.parent().unwrap()) | ||
204 | .args(&["--print", "sysroot"]) | ||
205 | .output()?; | ||
206 | if !rustc_output.status.success() { | ||
207 | failure::bail!("failed to locate sysroot") | ||
208 | } | ||
209 | let stdout = String::from_utf8(rustc_output.stdout)?; | ||
210 | let sysroot_path = Path::new(stdout.trim()); | ||
211 | let src = sysroot_path.join("lib/rustlib/src/rust/src"); | ||
212 | |||
213 | let crates: &[(&str, &[&str])] = &[ | ||
214 | ( | ||
215 | "std", | ||
216 | &[ | ||
217 | "alloc_jemalloc", | ||
218 | "alloc_system", | ||
219 | "panic_abort", | ||
220 | "rand", | ||
221 | "compiler_builtins", | ||
222 | "unwind", | ||
223 | "rustc_asan", | ||
224 | "rustc_lsan", | ||
225 | "rustc_msan", | ||
226 | "rustc_tsan", | ||
227 | "build_helper", | ||
228 | ], | ||
229 | ), | ||
230 | ("core", &[]), | ||
231 | ("alloc", &[]), | ||
232 | ("collections", &[]), | ||
233 | ("libc", &[]), | ||
234 | ("panic_unwind", &[]), | ||
235 | ("proc_macro", &[]), | ||
236 | ("rustc_unicode", &[]), | ||
237 | ("std_unicode", &[]), | ||
238 | ("test", &[]), | ||
239 | // Feature gated | ||
240 | ("alloc_jemalloc", &[]), | ||
241 | ("alloc_system", &[]), | ||
242 | ("compiler_builtins", &[]), | ||
243 | ("getopts", &[]), | ||
244 | ("panic_unwind", &[]), | ||
245 | ("panic_abort", &[]), | ||
246 | ("rand", &[]), | ||
247 | ("term", &[]), | ||
248 | ("unwind", &[]), | ||
249 | // Dependencies | ||
250 | ("build_helper", &[]), | ||
251 | ("rustc_asan", &[]), | ||
252 | ("rustc_lsan", &[]), | ||
253 | ("rustc_msan", &[]), | ||
254 | ("rustc_tsan", &[]), | ||
255 | ("syntax", &[]), | ||
256 | ]; | ||
257 | |||
258 | Ok(Sysroot { | ||
259 | crates: FxHashMap::default(), | ||
260 | }) | ||
261 | } | ||
262 | |||
163 | fn find_cargo_toml(path: &Path) -> Result<PathBuf> { | 263 | fn find_cargo_toml(path: &Path) -> Result<PathBuf> { |
164 | if path.ends_with("Cargo.toml") { | 264 | if path.ends_with("Cargo.toml") { |
165 | return Ok(path.to_path_buf()); | 265 | return Ok(path.to_path_buf()); |
@@ -190,17 +290,3 @@ impl TargetKind { | |||
190 | TargetKind::Other | 290 | TargetKind::Other |
191 | } | 291 | } |
192 | } | 292 | } |
193 | |||
194 | pub fn workspace_loader() -> (Worker<PathBuf, Result<CargoWorkspace>>, WorkerHandle) { | ||
195 | thread_worker::spawn::<PathBuf, Result<CargoWorkspace>, _>( | ||
196 | "workspace loader", | ||
197 | 1, | ||
198 | |input_receiver, output_sender| { | ||
199 | input_receiver | ||
200 | .into_iter() | ||
201 | .map(|path| CargoWorkspace::from_cargo_metadata(path.as_path())) | ||
202 | .try_for_each(|it| output_sender.send(it)) | ||
203 | .unwrap() | ||
204 | }, | ||
205 | ) | ||
206 | } | ||