aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/project_model/sysroot.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src/project_model/sysroot.rs')
-rw-r--r--crates/ra_lsp_server/src/project_model/sysroot.rs132
1 files changed, 132 insertions, 0 deletions
diff --git a/crates/ra_lsp_server/src/project_model/sysroot.rs b/crates/ra_lsp_server/src/project_model/sysroot.rs
new file mode 100644
index 000000000..1dbab57f8
--- /dev/null
+++ b/crates/ra_lsp_server/src/project_model/sysroot.rs
@@ -0,0 +1,132 @@
1use std::{
2 path::{Path, PathBuf},
3 process::Command,
4};
5
6use ra_syntax::SmolStr;
7use ra_arena::{Arena, RawId, impl_arena_id};
8
9use crate::Result;
10
11#[derive(Debug, Clone)]
12pub struct Sysroot {
13 crates: Arena<SysrootCrate, SysrootCrateData>,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub struct SysrootCrate(RawId);
18impl_arena_id!(SysrootCrate);
19
20#[derive(Debug, Clone)]
21struct SysrootCrateData {
22 name: SmolStr,
23 root: PathBuf,
24 deps: Vec<SysrootCrate>,
25}
26
27impl Sysroot {
28 pub(crate) fn std(&self) -> Option<SysrootCrate> {
29 self.by_name("std")
30 }
31
32 pub(crate) fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + 'a {
33 self.crates.iter().map(|(id, _data)| id)
34 }
35
36 pub(super) fn discover(cargo_toml: &Path) -> Result<Sysroot> {
37 let rustc_output = Command::new("rustc")
38 .current_dir(cargo_toml.parent().unwrap())
39 .args(&["--print", "sysroot"])
40 .output()?;
41 if !rustc_output.status.success() {
42 failure::bail!("failed to locate sysroot")
43 }
44 let stdout = String::from_utf8(rustc_output.stdout)?;
45 let sysroot_path = Path::new(stdout.trim());
46 let src = sysroot_path.join("lib/rustlib/src/rust/src");
47
48 let mut sysroot = Sysroot {
49 crates: Arena::default(),
50 };
51 for name in SYSROOT_CRATES.trim().lines() {
52 let root = src.join(format!("lib{}", name)).join("lib.rs");
53 if root.exists() {
54 sysroot.crates.alloc(SysrootCrateData {
55 name: name.into(),
56 root,
57 deps: Vec::new(),
58 });
59 }
60 }
61 if let Some(std) = sysroot.std() {
62 for dep in STD_DEPS.trim().lines() {
63 if let Some(dep) = sysroot.by_name(dep) {
64 sysroot.crates[std].deps.push(dep)
65 }
66 }
67 }
68 Ok(sysroot)
69 }
70
71 fn by_name(&self, name: &str) -> Option<SysrootCrate> {
72 self.crates
73 .iter()
74 .find(|(_id, data)| data.name == name)
75 .map(|(id, _data)| id)
76 }
77}
78
79impl SysrootCrate {
80 pub(crate) fn name(self, sysroot: &Sysroot) -> &SmolStr {
81 &sysroot.crates[self].name
82 }
83 pub(crate) fn root(self, sysroot: &Sysroot) -> &Path {
84 sysroot.crates[self].root.as_path()
85 }
86 pub(crate) fn root_dir(self, sysroot: &Sysroot) -> &Path {
87 self.root(sysroot).parent().unwrap()
88 }
89 pub(crate) fn deps<'a>(self, sysroot: &'a Sysroot) -> impl Iterator<Item = SysrootCrate> + 'a {
90 sysroot.crates[self].deps.iter().map(|&it| it)
91 }
92}
93
94const SYSROOT_CRATES: &str = "
95std
96core
97alloc
98collections
99libc
100panic_unwind
101proc_macro
102rustc_unicode
103std_unicode
104test
105alloc_jemalloc
106alloc_system
107compiler_builtins
108getopts
109panic_unwind
110panic_abort
111rand
112term
113unwind
114build_helper
115rustc_asan
116rustc_lsan
117rustc_msan
118rustc_tsan
119syntax";
120
121const STD_DEPS: &str = "
122alloc_jemalloc
123alloc_system
124panic_abort
125rand
126compiler_builtins
127unwind
128rustc_asan
129rustc_lsan
130rustc_msan
131rustc_tsan
132build_helper";