diff options
Diffstat (limited to 'crates/server/src/project_model.rs')
-rw-r--r-- | crates/server/src/project_model.rs | 175 |
1 files changed, 0 insertions, 175 deletions
diff --git a/crates/server/src/project_model.rs b/crates/server/src/project_model.rs deleted file mode 100644 index 359cf787d..000000000 --- a/crates/server/src/project_model.rs +++ /dev/null | |||
@@ -1,175 +0,0 @@ | |||
1 | use std::{ | ||
2 | collections::{HashMap, HashSet}, | ||
3 | path::{Path, PathBuf}, | ||
4 | }; | ||
5 | use cargo_metadata::{metadata_run, CargoOpt}; | ||
6 | use libsyntax2::SmolStr; | ||
7 | |||
8 | use { | ||
9 | Result, | ||
10 | thread_watcher::{Worker, ThreadWatcher}, | ||
11 | }; | ||
12 | |||
13 | #[derive(Debug, Clone)] | ||
14 | pub struct CargoWorkspace { | ||
15 | packages: Vec<PackageData>, | ||
16 | targets: Vec<TargetData>, | ||
17 | } | ||
18 | |||
19 | #[derive(Clone, Copy, Debug, Serialize)] | ||
20 | pub struct Package(usize); | ||
21 | #[derive(Clone, Copy, Debug, Serialize)] | ||
22 | pub struct Target(usize); | ||
23 | |||
24 | #[derive(Debug, Clone)] | ||
25 | struct PackageData { | ||
26 | name: SmolStr, | ||
27 | manifest: PathBuf, | ||
28 | targets: Vec<Target>, | ||
29 | is_member: bool, | ||
30 | } | ||
31 | |||
32 | #[derive(Debug, Clone)] | ||
33 | struct TargetData { | ||
34 | pkg: Package, | ||
35 | name: SmolStr, | ||
36 | root: PathBuf, | ||
37 | kind: TargetKind, | ||
38 | } | ||
39 | |||
40 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
41 | pub enum TargetKind { | ||
42 | Bin, Lib, Example, Test, Bench, Other, | ||
43 | } | ||
44 | |||
45 | impl Package { | ||
46 | pub fn name(self, ws: &CargoWorkspace) -> &str { | ||
47 | ws.pkg(self).name.as_str() | ||
48 | } | ||
49 | pub fn root(self, ws: &CargoWorkspace) -> &Path { | ||
50 | ws.pkg(self).manifest.parent().unwrap() | ||
51 | } | ||
52 | pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item=Target> + 'a { | ||
53 | ws.pkg(self).targets.iter().cloned() | ||
54 | } | ||
55 | pub fn is_member(self, ws: &CargoWorkspace) -> bool { | ||
56 | ws.pkg(self).is_member | ||
57 | } | ||
58 | } | ||
59 | |||
60 | impl Target { | ||
61 | pub fn package(self, ws: &CargoWorkspace) -> Package { | ||
62 | ws.tgt(self).pkg | ||
63 | } | ||
64 | pub fn name(self, ws: &CargoWorkspace) -> &str { | ||
65 | ws.tgt(self).name.as_str() | ||
66 | } | ||
67 | pub fn root(self, ws: &CargoWorkspace) -> &Path { | ||
68 | ws.tgt(self).root.as_path() | ||
69 | } | ||
70 | pub fn kind(self, ws: &CargoWorkspace) -> TargetKind { | ||
71 | ws.tgt(self).kind | ||
72 | } | ||
73 | } | ||
74 | |||
75 | impl CargoWorkspace { | ||
76 | pub fn from_cargo_metadata(path: &Path) -> Result<CargoWorkspace> { | ||
77 | let cargo_toml = find_cargo_toml(path)?; | ||
78 | let meta = metadata_run( | ||
79 | Some(cargo_toml.as_path()), | ||
80 | true, | ||
81 | Some(CargoOpt::AllFeatures) | ||
82 | ).map_err(|e| format_err!("cargo metadata failed: {}", e))?; | ||
83 | let mut pkg_by_id = HashMap::new(); | ||
84 | let mut packages = Vec::new(); | ||
85 | let mut targets = Vec::new(); | ||
86 | |||
87 | let ws_members: HashSet<String> = meta.workspace_members | ||
88 | .into_iter() | ||
89 | .map(|it| it.raw) | ||
90 | .collect(); | ||
91 | |||
92 | for meta_pkg in meta.packages { | ||
93 | let pkg = Package(packages.len()); | ||
94 | let is_member = ws_members.contains(&meta_pkg.id); | ||
95 | pkg_by_id.insert(meta_pkg.id.clone(), pkg); | ||
96 | let mut pkg_data = PackageData { | ||
97 | name: meta_pkg.name.into(), | ||
98 | manifest: PathBuf::from(meta_pkg.manifest_path), | ||
99 | targets: Vec::new(), | ||
100 | is_member, | ||
101 | }; | ||
102 | for meta_tgt in meta_pkg.targets { | ||
103 | let tgt = Target(targets.len()); | ||
104 | targets.push(TargetData { | ||
105 | pkg, | ||
106 | name: meta_tgt.name.into(), | ||
107 | root: PathBuf::from(meta_tgt.src_path), | ||
108 | kind: TargetKind::new(meta_tgt.kind.as_slice()), | ||
109 | }); | ||
110 | pkg_data.targets.push(tgt); | ||
111 | } | ||
112 | packages.push(pkg_data) | ||
113 | } | ||
114 | |||
115 | Ok(CargoWorkspace { packages, targets }) | ||
116 | } | ||
117 | pub fn packages<'a>(&'a self) -> impl Iterator<Item=Package> + 'a { | ||
118 | (0..self.packages.len()).map(Package) | ||
119 | } | ||
120 | pub fn target_by_root(&self, root: &Path) -> Option<Target> { | ||
121 | self.packages() | ||
122 | .filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root)) | ||
123 | .next() | ||
124 | } | ||
125 | fn pkg(&self, pkg: Package) -> &PackageData { | ||
126 | &self.packages[pkg.0] | ||
127 | } | ||
128 | fn tgt(&self, tgt: Target) -> &TargetData { | ||
129 | &self.targets[tgt.0] | ||
130 | } | ||
131 | } | ||
132 | |||
133 | fn find_cargo_toml(path: &Path) -> Result<PathBuf> { | ||
134 | if path.ends_with("Cargo.toml") { | ||
135 | return Ok(path.to_path_buf()); | ||
136 | } | ||
137 | let mut curr = Some(path); | ||
138 | while let Some(path) = curr { | ||
139 | let candidate = path.join("Cargo.toml"); | ||
140 | if candidate.exists() { | ||
141 | return Ok(candidate); | ||
142 | } | ||
143 | curr = path.parent(); | ||
144 | } | ||
145 | bail!("can't find Cargo.toml at {}", path.display()) | ||
146 | } | ||
147 | |||
148 | impl TargetKind { | ||
149 | fn new(kinds: &[String]) -> TargetKind { | ||
150 | for kind in kinds { | ||
151 | return match kind.as_str() { | ||
152 | "bin" => TargetKind::Bin, | ||
153 | "test" => TargetKind::Test, | ||
154 | "bench" => TargetKind::Bench, | ||
155 | "example" => TargetKind::Example, | ||
156 | _ if kind.contains("lib") => TargetKind::Lib, | ||
157 | _ => continue, | ||
158 | } | ||
159 | } | ||
160 | TargetKind::Other | ||
161 | } | ||
162 | } | ||
163 | |||
164 | pub fn workspace_loader() -> (Worker<PathBuf, Result<CargoWorkspace>>, ThreadWatcher) { | ||
165 | Worker::<PathBuf, Result<CargoWorkspace>>::spawn( | ||
166 | "workspace loader", | ||
167 | 1, | ||
168 | |input_receiver, output_sender| { | ||
169 | input_receiver | ||
170 | .into_iter() | ||
171 | .map(|path| CargoWorkspace::from_cargo_metadata(path.as_path())) | ||
172 | .for_each(|it| output_sender.send(it)) | ||
173 | } | ||
174 | ) | ||
175 | } | ||