aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_db/src/input.rs59
1 files changed, 54 insertions, 5 deletions
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index ead8dfe48..7c3dd9296 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -7,11 +7,13 @@
7/// actual IO is done and lowered to input. 7/// actual IO is done and lowered to input.
8use std::sync::Arc; 8use std::sync::Arc;
9 9
10use rustc_hash::{FxHashMap};
11use relative_path::RelativePathBuf; 10use relative_path::RelativePathBuf;
12use ra_syntax::SmolStr; 11use rustc_hash::FxHashMap;
13use salsa; 12use salsa;
14 13
14use ra_syntax::SmolStr;
15use rustc_hash::FxHashSet;
16
15/// `FileId` is an integer which uniquely identifies a file. File paths are 17/// `FileId` is an integer which uniquely identifies a file. File paths are
16/// messy and system-dependent, so most of the code should work directly with 18/// messy and system-dependent, so most of the code should work directly with
17/// `FileId`, without inspecting the path. The mapping between `FileId` and path 19/// `FileId`, without inspecting the path. The mapping between `FileId` and path
@@ -92,10 +94,11 @@ impl CrateGraph {
92 assert!(prev.is_none()); 94 assert!(prev.is_none());
93 crate_id 95 crate_id
94 } 96 }
95 // FIXME: check that we don't have cycles here.
96 // Just a simple depth first search from `to` should work,
97 // the graph is small.
98 pub fn add_dep(&mut self, from: CrateId, name: SmolStr, to: CrateId) { 97 pub fn add_dep(&mut self, from: CrateId, name: SmolStr, to: CrateId) {
98 let mut visited = FxHashSet::default();
99 if self.dfs_find(from, to, &mut visited) {
100 panic!("Cycle dependencies found.")
101 }
99 self.arena.get_mut(&from).unwrap().add_dep(name, to) 102 self.arena.get_mut(&from).unwrap().add_dep(name, to)
100 } 103 }
101 pub fn is_empty(&self) -> bool { 104 pub fn is_empty(&self) -> bool {
@@ -117,6 +120,52 @@ impl CrateGraph {
117 ) -> impl Iterator<Item = &'a Dependency> + 'a { 120 ) -> impl Iterator<Item = &'a Dependency> + 'a {
118 self.arena[&crate_id].dependencies.iter() 121 self.arena[&crate_id].dependencies.iter()
119 } 122 }
123 fn dfs_find(&self, target: CrateId, from: CrateId, visited: &mut FxHashSet<CrateId>) -> bool {
124 if !visited.insert(from) {
125 return false;
126 }
127
128 for dep in self.dependencies(from) {
129 let crate_id = dep.crate_id();
130 if crate_id == target {
131 return true;
132 }
133
134 if self.dfs_find(target, crate_id, visited) {
135 return true;
136 }
137 }
138 return false;
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use super::{CrateGraph, FxHashMap, FileId, SmolStr};
145
146 #[test]
147 #[should_panic]
148 fn it_should_painc_because_of_cycle_dependencies() {
149 let mut graph = CrateGraph::default();
150 let crate1 = graph.add_crate_root(FileId(1u32));
151 let crate2 = graph.add_crate_root(FileId(2u32));
152 let crate3 = graph.add_crate_root(FileId(3u32));
153 graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
154 graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
155 graph.add_dep(crate3, SmolStr::new("crate1"), crate1);
156 }
157
158 #[test]
159 fn it_works() {
160 let mut graph = CrateGraph {
161 arena: FxHashMap::default(),
162 };
163 let crate1 = graph.add_crate_root(FileId(1u32));
164 let crate2 = graph.add_crate_root(FileId(2u32));
165 let crate3 = graph.add_crate_root(FileId(3u32));
166 graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
167 graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
168 }
120} 169}
121 170
122salsa::query_group! { 171salsa::query_group! {