aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/project_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src/project_model.rs')
-rw-r--r--crates/ra_lsp_server/src/project_model.rs116
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 @@
1use std::path::{Path, PathBuf}; 1use std::{
2 path::{Path, PathBuf},
3 process::Command,
4};
2 5
3use cargo_metadata::{metadata_run, CargoOpt}; 6use cargo_metadata::{metadata_run, CargoOpt};
4use ra_syntax::SmolStr; 7use ra_syntax::SmolStr;
@@ -9,6 +12,36 @@ use thread_worker::{WorkerHandle, Worker};
9 12
10use crate::Result; 13use crate::Result;
11 14
15#[derive(Debug, Clone)]
16pub struct ProjectWorkspace {
17 pub(crate) cargo: CargoWorkspace,
18 pub(crate) sysroot: Sysroot,
19}
20
21impl 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
31pub 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)]
100pub(crate) struct Sysroot {
101 crates: FxHashMap<SmolStr, PathBuf>,
102}
103
66impl Package { 104impl 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
201fn 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
163fn find_cargo_toml(path: &Path) -> Result<PathBuf> { 263fn 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
194pub 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}