aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_project_model/src/lib.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-06 21:54:33 +0000
committerFlorian Diebold <[email protected]>2019-02-09 10:15:25 +0000
commitddbf43b630fa8159ab2ea5e959393bff44e0c73b (patch)
treef5ee2104b2990086a3ba7a51847be912ce293a7d /crates/ra_project_model/src/lib.rs
parentfcd615e4b76264b4fff7b5be454787bb6a4252ea (diff)
Move crate graph generation to ra_project_model
Diffstat (limited to 'crates/ra_project_model/src/lib.rs')
-rw-r--r--crates/ra_project_model/src/lib.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 3a7bbace7..30612ac84 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -4,6 +4,10 @@ mod sysroot;
4use std::path::{Path, PathBuf}; 4use std::path::{Path, PathBuf};
5 5
6use failure::bail; 6use failure::bail;
7use rustc_hash::FxHashMap;
8
9use ra_db::{CrateGraph, FileId};
10use ra_vfs::Vfs;
7 11
8pub use crate::{ 12pub use crate::{
9 cargo_workspace::{CargoWorkspace, Package, Target, TargetKind}, 13 cargo_workspace::{CargoWorkspace, Package, Target, TargetKind},
@@ -27,6 +31,90 @@ impl ProjectWorkspace {
27 let res = ProjectWorkspace { cargo, sysroot }; 31 let res = ProjectWorkspace { cargo, sysroot };
28 Ok(res) 32 Ok(res)
29 } 33 }
34
35 pub fn to_crate_graph(&self, vfs: &mut Vfs) -> CrateGraph {
36 let mut crate_graph = CrateGraph::default();
37 let mut sysroot_crates = FxHashMap::default();
38 for krate in self.sysroot.crates() {
39 if let Some(file_id) = vfs.load(krate.root(&self.sysroot)) {
40 let file_id = FileId(file_id.0.into());
41 sysroot_crates.insert(krate, crate_graph.add_crate_root(file_id));
42 }
43 }
44 for from in self.sysroot.crates() {
45 for to in from.deps(&self.sysroot) {
46 let name = to.name(&self.sysroot);
47 if let (Some(&from), Some(&to)) =
48 (sysroot_crates.get(&from), sysroot_crates.get(&to))
49 {
50 if let Err(_) = crate_graph.add_dep(from, name.clone(), to) {
51 log::error!("cyclic dependency between sysroot crates")
52 }
53 }
54 }
55 }
56
57 let libstd = self.sysroot.std().and_then(|it| sysroot_crates.get(&it).map(|&it| it));
58
59 let mut pkg_to_lib_crate = FxHashMap::default();
60 let mut pkg_crates = FxHashMap::default();
61 // Next, create crates for each package, target pair
62 for pkg in self.cargo.packages() {
63 let mut lib_tgt = None;
64 for tgt in pkg.targets(&self.cargo) {
65 let root = tgt.root(&self.cargo);
66 if let Some(file_id) = vfs.load(root) {
67 let file_id = FileId(file_id.0.into());
68 let crate_id = crate_graph.add_crate_root(file_id);
69 if tgt.kind(&self.cargo) == TargetKind::Lib {
70 lib_tgt = Some(crate_id);
71 pkg_to_lib_crate.insert(pkg, crate_id);
72 }
73 pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
74 }
75 }
76
77 // Set deps to the std and to the lib target of the current package
78 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
79 if let Some(to) = lib_tgt {
80 if to != from {
81 if let Err(_) = crate_graph.add_dep(from, pkg.name(&self.cargo).into(), to)
82 {
83 log::error!(
84 "cyclic dependency between targets of {}",
85 pkg.name(&self.cargo)
86 )
87 }
88 }
89 }
90 if let Some(std) = libstd {
91 if let Err(_) = crate_graph.add_dep(from, "std".into(), std) {
92 log::error!("cyclic dependency on std for {}", pkg.name(&self.cargo))
93 }
94 }
95 }
96 }
97
98 // Now add a dep ednge from all targets of upstream to the lib
99 // target of downstream.
100 for pkg in self.cargo.packages() {
101 for dep in pkg.dependencies(&self.cargo) {
102 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
103 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
104 if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) {
105 log::error!(
106 "cyclic dependency {} -> {}",
107 pkg.name(&self.cargo),
108 dep.pkg.name(&self.cargo)
109 )
110 }
111 }
112 }
113 }
114 }
115
116 crate_graph
117 }
30} 118}
31 119
32fn find_cargo_toml(path: &Path) -> Result<PathBuf> { 120fn find_cargo_toml(path: &Path) -> Result<PathBuf> {