aboutsummaryrefslogtreecommitdiff
path: root/crates/server/src/project_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/server/src/project_model.rs')
-rw-r--r--crates/server/src/project_model.rs54
1 files changed, 44 insertions, 10 deletions
diff --git a/crates/server/src/project_model.rs b/crates/server/src/project_model.rs
index a33b34dd0..1c5954dad 100644
--- a/crates/server/src/project_model.rs
+++ b/crates/server/src/project_model.rs
@@ -2,30 +2,35 @@ use std::{
2 collections::HashMap, 2 collections::HashMap,
3 path::{Path, PathBuf}, 3 path::{Path, PathBuf},
4}; 4};
5use libsyntax2::SmolStr;
6use cargo_metadata::{metadata_run, CargoOpt}; 5use cargo_metadata::{metadata_run, CargoOpt};
7use Result; 6use crossbeam_channel::{bounded, Sender, Receiver};
7use libsyntax2::SmolStr;
8
9use {
10 Result,
11 thread_watcher::ThreadWatcher,
12};
8 13
9#[derive(Debug)] 14#[derive(Debug, Serialize, Clone)]
10pub struct CargoWorkspace { 15pub struct CargoWorkspace {
11 ws_members: Vec<Package>, 16 ws_members: Vec<Package>,
12 packages: Vec<PackageData>, 17 packages: Vec<PackageData>,
13 targets: Vec<TargetData>, 18 targets: Vec<TargetData>,
14} 19}
15 20
16#[derive(Clone, Copy, Debug)] 21#[derive(Clone, Copy, Debug, Serialize)]
17pub struct Package(usize); 22pub struct Package(usize);
18#[derive(Clone, Copy, Debug)] 23#[derive(Clone, Copy, Debug, Serialize)]
19pub struct Target(usize); 24pub struct Target(usize);
20 25
21#[derive(Debug)] 26#[derive(Debug, Serialize, Clone)]
22struct PackageData { 27struct PackageData {
23 name: SmolStr, 28 name: SmolStr,
24 manifest: PathBuf, 29 manifest: PathBuf,
25 targets: Vec<Target> 30 targets: Vec<Target>
26} 31}
27 32
28#[derive(Debug)] 33#[derive(Debug, Serialize, Clone)]
29struct TargetData { 34struct TargetData {
30 pkg: Package, 35 pkg: Package,
31 name: SmolStr, 36 name: SmolStr,
@@ -33,7 +38,7 @@ struct TargetData {
33 kind: TargetKind, 38 kind: TargetKind,
34} 39}
35 40
36#[derive(Clone, Copy, PartialEq, Eq, Debug)] 41#[derive(Debug, Serialize, Clone, Copy, PartialEq, Eq)]
37pub enum TargetKind { 42pub enum TargetKind {
38 Bin, Lib, Example, Test, Bench, Other, 43 Bin, Lib, Example, Test, Bench, Other,
39} 44}
@@ -66,9 +71,10 @@ impl Target {
66} 71}
67 72
68impl CargoWorkspace { 73impl CargoWorkspace {
69 pub fn from_path(path: &Path) -> Result<CargoWorkspace> { 74 pub fn from_cargo_metadata(path: &Path) -> Result<CargoWorkspace> {
75 let cargo_toml = find_cargo_toml(path)?;
70 let meta = metadata_run( 76 let meta = metadata_run(
71 Some(path), 77 Some(cargo_toml.as_path()),
72 true, 78 true,
73 Some(CargoOpt::AllFeatures) 79 Some(CargoOpt::AllFeatures)
74 ).map_err(|e| format_err!("cargo metadata failed: {}", e))?; 80 ).map_err(|e| format_err!("cargo metadata failed: {}", e))?;
@@ -121,6 +127,21 @@ impl CargoWorkspace {
121 } 127 }
122} 128}
123 129
130fn find_cargo_toml(path: &Path) -> Result<PathBuf> {
131 if path.ends_with("Cargo.toml") {
132 return Ok(path.to_path_buf());
133 }
134 let mut curr = Some(path);
135 while let Some(path) = curr {
136 let candidate = path.join("Cargo.toml");
137 if candidate.exists() {
138 return Ok(candidate);
139 }
140 curr = path.parent();
141 }
142 bail!("can't find Cargo.toml at {}", path.display())
143}
144
124impl TargetKind { 145impl TargetKind {
125 fn new(kinds: &[String]) -> TargetKind { 146 fn new(kinds: &[String]) -> TargetKind {
126 for kind in kinds { 147 for kind in kinds {
@@ -136,3 +157,16 @@ impl TargetKind {
136 TargetKind::Other 157 TargetKind::Other
137 } 158 }
138} 159}
160
161pub fn workspace_loader() -> (Sender<PathBuf>, Receiver<Result<CargoWorkspace>>, ThreadWatcher) {
162 let (path_sender, path_receiver) = bounded::<PathBuf>(16);
163 let (ws_sender, ws_receiver) = bounded::<Result<CargoWorkspace>>(1);
164 let thread = ThreadWatcher::spawn("workspace loader", move || {
165 path_receiver
166 .into_iter()
167 .map(|path| CargoWorkspace::from_cargo_metadata(path.as_path()))
168 .for_each(|it| ws_sender.send(it))
169 });
170
171 (path_sender, ws_receiver, thread)
172}