diff options
Diffstat (limited to 'crates/ra_project_model')
-rw-r--r-- | crates/ra_project_model/Cargo.toml | 4 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 88 |
2 files changed, 91 insertions, 1 deletions
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml index 5215e5232..f65aabad7 100644 --- a/crates/ra_project_model/Cargo.toml +++ b/crates/ra_project_model/Cargo.toml | |||
@@ -7,7 +7,7 @@ authors = ["Aleksey Kladov <[email protected]>"] | |||
7 | [dependencies] | 7 | [dependencies] |
8 | # itertools = "0.8.0" | 8 | # itertools = "0.8.0" |
9 | # join_to_string = "0.1.3" | 9 | # join_to_string = "0.1.3" |
10 | # log = "0.4.5" | 10 | log = "0.4.5" |
11 | # relative-path = "0.4.0" | 11 | # relative-path = "0.4.0" |
12 | # rayon = "1.0.2" | 12 | # rayon = "1.0.2" |
13 | # fst = "0.3.1" | 13 | # fst = "0.3.1" |
@@ -25,6 +25,8 @@ walkdir = "2.2.7" | |||
25 | cargo_metadata = "0.7.0" | 25 | cargo_metadata = "0.7.0" |
26 | 26 | ||
27 | ra_arena = { path = "../ra_arena" } | 27 | ra_arena = { path = "../ra_arena" } |
28 | ra_db = { path = "../ra_db" } | ||
29 | ra_vfs = { path = "../ra_vfs" } | ||
28 | 30 | ||
29 | [dev-dependencies] | 31 | [dev-dependencies] |
30 | test_utils = { path = "../test_utils" } | 32 | test_utils = { path = "../test_utils" } |
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; | |||
4 | use std::path::{Path, PathBuf}; | 4 | use std::path::{Path, PathBuf}; |
5 | 5 | ||
6 | use failure::bail; | 6 | use failure::bail; |
7 | use rustc_hash::FxHashMap; | ||
8 | |||
9 | use ra_db::{CrateGraph, FileId}; | ||
10 | use ra_vfs::Vfs; | ||
7 | 11 | ||
8 | pub use crate::{ | 12 | pub 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 | ||
32 | fn find_cargo_toml(path: &Path) -> Result<PathBuf> { | 120 | fn find_cargo_toml(path: &Path) -> Result<PathBuf> { |