aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_project_model/src/cargo_workspace.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_project_model/src/cargo_workspace.rs')
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs42
1 files changed, 22 insertions, 20 deletions
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 4b7444039..8ce63ab3c 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -1,14 +1,10 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::{ 3use std::{ffi::OsStr, ops, path::Path, process::Command};
4 ffi::OsStr,
5 ops,
6 path::{Path, PathBuf},
7 process::Command,
8};
9 4
10use anyhow::{Context, Result}; 5use anyhow::{Context, Result};
11use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId}; 6use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId};
7use paths::{AbsPath, AbsPathBuf};
12use ra_arena::{Arena, Idx}; 8use ra_arena::{Arena, Idx};
13use ra_db::Edition; 9use ra_db::Edition;
14use rustc_hash::FxHashMap; 10use rustc_hash::FxHashMap;
@@ -20,11 +16,14 @@ use rustc_hash::FxHashMap;
20/// `CrateGraph`. `CrateGraph` is lower-level: it knows only about the crates, 16/// `CrateGraph`. `CrateGraph` is lower-level: it knows only about the crates,
21/// while this knows about `Packages` & `Targets`: purely cargo-related 17/// while this knows about `Packages` & `Targets`: purely cargo-related
22/// concepts. 18/// concepts.
19///
20/// We use absolute paths here, `cargo metadata` guarantees to always produce
21/// abs paths.
23#[derive(Debug, Clone)] 22#[derive(Debug, Clone)]
24pub struct CargoWorkspace { 23pub struct CargoWorkspace {
25 packages: Arena<PackageData>, 24 packages: Arena<PackageData>,
26 targets: Arena<TargetData>, 25 targets: Arena<TargetData>,
27 workspace_root: PathBuf, 26 workspace_root: AbsPathBuf,
28} 27}
29 28
30impl ops::Index<Package> for CargoWorkspace { 29impl ops::Index<Package> for CargoWorkspace {
@@ -80,15 +79,15 @@ pub type Target = Idx<TargetData>;
80pub struct PackageData { 79pub struct PackageData {
81 pub version: String, 80 pub version: String,
82 pub name: String, 81 pub name: String,
83 pub manifest: PathBuf, 82 pub manifest: AbsPathBuf,
84 pub targets: Vec<Target>, 83 pub targets: Vec<Target>,
85 pub is_member: bool, 84 pub is_member: bool,
86 pub dependencies: Vec<PackageDependency>, 85 pub dependencies: Vec<PackageDependency>,
87 pub edition: Edition, 86 pub edition: Edition,
88 pub features: Vec<String>, 87 pub features: Vec<String>,
89 pub cfgs: Vec<String>, 88 pub cfgs: Vec<String>,
90 pub out_dir: Option<PathBuf>, 89 pub out_dir: Option<AbsPathBuf>,
91 pub proc_macro_dylib_path: Option<PathBuf>, 90 pub proc_macro_dylib_path: Option<AbsPathBuf>,
92} 91}
93 92
94#[derive(Debug, Clone)] 93#[derive(Debug, Clone)]
@@ -101,7 +100,7 @@ pub struct PackageDependency {
101pub struct TargetData { 100pub struct TargetData {
102 pub package: Package, 101 pub package: Package,
103 pub name: String, 102 pub name: String,
104 pub root: PathBuf, 103 pub root: AbsPathBuf,
105 pub kind: TargetKind, 104 pub kind: TargetKind,
106 pub is_proc_macro: bool, 105 pub is_proc_macro: bool,
107} 106}
@@ -135,7 +134,7 @@ impl TargetKind {
135} 134}
136 135
137impl PackageData { 136impl PackageData {
138 pub fn root(&self) -> &Path { 137 pub fn root(&self) -> &AbsPath {
139 self.manifest.parent().unwrap() 138 self.manifest.parent().unwrap()
140 } 139 }
141} 140}
@@ -193,7 +192,7 @@ impl CargoWorkspace {
193 let pkg = packages.alloc(PackageData { 192 let pkg = packages.alloc(PackageData {
194 name, 193 name,
195 version: version.to_string(), 194 version: version.to_string(),
196 manifest: manifest_path, 195 manifest: AbsPathBuf::assert(manifest_path),
197 targets: Vec::new(), 196 targets: Vec::new(),
198 is_member, 197 is_member,
199 edition, 198 edition,
@@ -210,7 +209,7 @@ impl CargoWorkspace {
210 let tgt = targets.alloc(TargetData { 209 let tgt = targets.alloc(TargetData {
211 package: pkg, 210 package: pkg,
212 name: meta_tgt.name, 211 name: meta_tgt.name,
213 root: meta_tgt.src_path.clone(), 212 root: AbsPathBuf::assert(meta_tgt.src_path.clone()),
214 kind: TargetKind::new(meta_tgt.kind.as_slice()), 213 kind: TargetKind::new(meta_tgt.kind.as_slice()),
215 is_proc_macro, 214 is_proc_macro,
216 }); 215 });
@@ -246,16 +245,17 @@ impl CargoWorkspace {
246 packages[source].features.extend(node.features); 245 packages[source].features.extend(node.features);
247 } 246 }
248 247
249 Ok(CargoWorkspace { packages, targets, workspace_root: meta.workspace_root }) 248 let workspace_root = AbsPathBuf::assert(meta.workspace_root);
249 Ok(CargoWorkspace { packages, targets, workspace_root: workspace_root })
250 } 250 }
251 251
252 pub fn packages<'a>(&'a self) -> impl Iterator<Item = Package> + ExactSizeIterator + 'a { 252 pub fn packages<'a>(&'a self) -> impl Iterator<Item = Package> + ExactSizeIterator + 'a {
253 self.packages.iter().map(|(id, _pkg)| id) 253 self.packages.iter().map(|(id, _pkg)| id)
254 } 254 }
255 255
256 pub fn target_by_root(&self, root: &Path) -> Option<Target> { 256 pub fn target_by_root(&self, root: &AbsPath) -> Option<Target> {
257 self.packages() 257 self.packages()
258 .filter_map(|pkg| self[pkg].targets.iter().find(|&&it| self[it].root == root)) 258 .filter_map(|pkg| self[pkg].targets.iter().find(|&&it| &self[it].root == root))
259 .next() 259 .next()
260 .copied() 260 .copied()
261 } 261 }
@@ -279,8 +279,8 @@ impl CargoWorkspace {
279 279
280#[derive(Debug, Clone, Default)] 280#[derive(Debug, Clone, Default)]
281pub struct ExternResources { 281pub struct ExternResources {
282 out_dirs: FxHashMap<PackageId, PathBuf>, 282 out_dirs: FxHashMap<PackageId, AbsPathBuf>,
283 proc_dylib_paths: FxHashMap<PackageId, PathBuf>, 283 proc_dylib_paths: FxHashMap<PackageId, AbsPathBuf>,
284 cfgs: FxHashMap<PackageId, Vec<String>>, 284 cfgs: FxHashMap<PackageId, Vec<String>>,
285} 285}
286 286
@@ -308,6 +308,7 @@ pub fn load_extern_resources(
308 if let Ok(message) = message { 308 if let Ok(message) = message {
309 match message { 309 match message {
310 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => { 310 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => {
311 let out_dir = AbsPathBuf::assert(out_dir);
311 res.out_dirs.insert(package_id.clone(), out_dir); 312 res.out_dirs.insert(package_id.clone(), out_dir);
312 res.cfgs.insert(package_id, cfgs); 313 res.cfgs.insert(package_id, cfgs);
313 } 314 }
@@ -317,7 +318,8 @@ pub fn load_extern_resources(
317 // Skip rmeta file 318 // Skip rmeta file
318 if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) 319 if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name))
319 { 320 {
320 res.proc_dylib_paths.insert(package_id, filename.clone()); 321 let filename = AbsPathBuf::assert(filename.clone());
322 res.proc_dylib_paths.insert(package_id, filename);
321 } 323 }
322 } 324 }
323 } 325 }