diff options
author | Aleksey Kladov <[email protected]> | 2018-08-31 17:14:08 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-31 17:14:08 +0100 |
commit | f2772e29aeda5e35c282f3b023ce9d470f3fb441 (patch) | |
tree | f517fd3d40f569de0d4dbb2529f38c9d470b2db9 /crates/libanalysis/src | |
parent | 7a5bc94774a50837f8c9bf8b96c8272882aca640 (diff) |
add crate graph
Diffstat (limited to 'crates/libanalysis/src')
-rw-r--r-- | crates/libanalysis/src/imp.rs | 53 | ||||
-rw-r--r-- | crates/libanalysis/src/lib.rs | 19 | ||||
-rw-r--r-- | crates/libanalysis/src/module_map.rs | 36 |
3 files changed, 95 insertions, 13 deletions
diff --git a/crates/libanalysis/src/imp.rs b/crates/libanalysis/src/imp.rs index 6a6e1e933..f1d72da15 100644 --- a/crates/libanalysis/src/imp.rs +++ b/crates/libanalysis/src/imp.rs | |||
@@ -5,7 +5,7 @@ use std::{ | |||
5 | }, | 5 | }, |
6 | fmt, | 6 | fmt, |
7 | time::Instant, | 7 | time::Instant, |
8 | collections::HashMap, | 8 | collections::{HashMap, HashSet, VecDeque}, |
9 | panic, | 9 | panic, |
10 | }; | 10 | }; |
11 | 11 | ||
@@ -23,7 +23,7 @@ use { | |||
23 | module_map::Problem, | 23 | module_map::Problem, |
24 | symbol_index::FileSymbols, | 24 | symbol_index::FileSymbols, |
25 | module_map::{ModuleMap, ChangeKind}, | 25 | module_map::{ModuleMap, ChangeKind}, |
26 | JobToken, | 26 | JobToken, CrateGraph, CrateId, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #[derive(Debug)] | 29 | #[derive(Debug)] |
@@ -37,7 +37,6 @@ impl AnalysisHostImpl { | |||
37 | data: Arc::new(WorldData::default()), | 37 | data: Arc::new(WorldData::default()), |
38 | } | 38 | } |
39 | } | 39 | } |
40 | |||
41 | pub fn analysis( | 40 | pub fn analysis( |
42 | &self, | 41 | &self, |
43 | file_resolver: Arc<dyn FileResolver>, | 42 | file_resolver: Arc<dyn FileResolver>, |
@@ -48,7 +47,6 @@ impl AnalysisHostImpl { | |||
48 | data: self.data.clone(), | 47 | data: self.data.clone(), |
49 | } | 48 | } |
50 | } | 49 | } |
51 | |||
52 | pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<String>)>) { | 50 | pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<String>)>) { |
53 | let data = self.data_mut(); | 51 | let data = self.data_mut(); |
54 | for (file_id, text) in changes { | 52 | for (file_id, text) in changes { |
@@ -71,7 +69,15 @@ impl AnalysisHostImpl { | |||
71 | } | 69 | } |
72 | } | 70 | } |
73 | } | 71 | } |
74 | 72 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { | |
73 | let mut visited = HashSet::new(); | ||
74 | for &file_id in graph.crate_roots.values() { | ||
75 | if !visited.insert(file_id) { | ||
76 | panic!("duplicate crate root: {:?}", file_id); | ||
77 | } | ||
78 | } | ||
79 | self.data_mut().crate_graph = graph; | ||
80 | } | ||
75 | fn data_mut(&mut self) -> &mut WorldData { | 81 | fn data_mut(&mut self) -> &mut WorldData { |
76 | Arc::make_mut(&mut self.data) | 82 | Arc::make_mut(&mut self.data) |
77 | } | 83 | } |
@@ -145,6 +151,33 @@ impl AnalysisImpl { | |||
145 | .collect() | 151 | .collect() |
146 | } | 152 | } |
147 | 153 | ||
154 | pub fn crate_root(&self, id: FileId) -> Vec<CrateId> { | ||
155 | let module_map = &self.data.module_map; | ||
156 | let crate_graph = &self.data.crate_graph; | ||
157 | let mut res = Vec::new(); | ||
158 | let mut work = VecDeque::new(); | ||
159 | work.push_back(id); | ||
160 | let mut visited = HashSet::new(); | ||
161 | while let Some(id) = work.pop_front() { | ||
162 | if let Some(crate_id) = crate_graph.crate_id_for_crate_root(id) { | ||
163 | res.push(crate_id); | ||
164 | continue; | ||
165 | } | ||
166 | let mid = module_map.file2module(id); | ||
167 | let parents = module_map | ||
168 | .parent_module_ids( | ||
169 | mid, | ||
170 | &*self.file_resolver, | ||
171 | &|file_id| self.file_syntax(file_id), | ||
172 | ) | ||
173 | .into_iter() | ||
174 | .map(|id| module_map.module2file(id)) | ||
175 | .filter(|&id| visited.insert(id)); | ||
176 | work.extend(parents); | ||
177 | } | ||
178 | res | ||
179 | } | ||
180 | |||
148 | pub fn approximately_resolve_symbol( | 181 | pub fn approximately_resolve_symbol( |
149 | &self, | 182 | &self, |
150 | id: FileId, | 183 | id: FileId, |
@@ -295,6 +328,7 @@ impl AnalysisImpl { | |||
295 | 328 | ||
296 | #[derive(Clone, Default, Debug)] | 329 | #[derive(Clone, Default, Debug)] |
297 | struct WorldData { | 330 | struct WorldData { |
331 | crate_graph: CrateGraph, | ||
298 | file_map: HashMap<FileId, Arc<FileData>>, | 332 | file_map: HashMap<FileId, Arc<FileData>>, |
299 | module_map: ModuleMap, | 333 | module_map: ModuleMap, |
300 | } | 334 | } |
@@ -356,3 +390,12 @@ impl SourceChange { | |||
356 | } | 390 | } |
357 | } | 391 | } |
358 | } | 392 | } |
393 | |||
394 | impl CrateGraph { | ||
395 | fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { | ||
396 | let (&crate_id, _) = self.crate_roots | ||
397 | .iter() | ||
398 | .find(|(_crate_id, &root_id)| root_id == file_id)?; | ||
399 | Some(crate_id) | ||
400 | } | ||
401 | } | ||
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs index a59fd1c09..041abbb89 100644 --- a/crates/libanalysis/src/lib.rs +++ b/crates/libanalysis/src/lib.rs | |||
@@ -15,7 +15,10 @@ mod module_map; | |||
15 | mod imp; | 15 | mod imp; |
16 | mod job; | 16 | mod job; |
17 | 17 | ||
18 | use std::sync::Arc; | 18 | use std::{ |
19 | sync::Arc, | ||
20 | collections::HashMap, | ||
21 | }; | ||
19 | 22 | ||
20 | use relative_path::{RelativePath, RelativePathBuf}; | 23 | use relative_path::{RelativePath, RelativePathBuf}; |
21 | use libsyntax2::{File, TextRange, TextUnit, AtomEdit}; | 24 | use libsyntax2::{File, TextRange, TextUnit, AtomEdit}; |
@@ -30,6 +33,14 @@ pub use job::{JobToken, JobHandle}; | |||
30 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 33 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
31 | pub struct FileId(pub u32); | 34 | pub struct FileId(pub u32); |
32 | 35 | ||
36 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
37 | pub struct CrateId(pub u32); | ||
38 | |||
39 | #[derive(Debug, Clone, Default)] | ||
40 | pub struct CrateGraph { | ||
41 | pub crate_roots: HashMap<CrateId, FileId>, | ||
42 | } | ||
43 | |||
33 | pub trait FileResolver: Send + Sync + 'static { | 44 | pub trait FileResolver: Send + Sync + 'static { |
34 | fn file_stem(&self, id: FileId) -> String; | 45 | fn file_stem(&self, id: FileId) -> String; |
35 | fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId>; | 46 | fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId>; |
@@ -53,6 +64,9 @@ impl AnalysisHost { | |||
53 | pub fn change_files(&mut self, mut changes: impl Iterator<Item=(FileId, Option<String>)>) { | 64 | pub fn change_files(&mut self, mut changes: impl Iterator<Item=(FileId, Option<String>)>) { |
54 | self.imp.change_files(&mut changes) | 65 | self.imp.change_files(&mut changes) |
55 | } | 66 | } |
67 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { | ||
68 | self.imp.set_crate_graph(graph) | ||
69 | } | ||
56 | } | 70 | } |
57 | 71 | ||
58 | #[derive(Debug)] | 72 | #[derive(Debug)] |
@@ -168,6 +182,9 @@ impl Analysis { | |||
168 | pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { | 182 | pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { |
169 | self.imp.parent_module(file_id) | 183 | self.imp.parent_module(file_id) |
170 | } | 184 | } |
185 | pub fn crate_root(&self, file_id: FileId) -> Vec<CrateId> { | ||
186 | self.imp.crate_root(file_id) | ||
187 | } | ||
171 | pub fn runnables(&self, file_id: FileId) -> Vec<Runnable> { | 188 | pub fn runnables(&self, file_id: FileId) -> Vec<Runnable> { |
172 | let file = self.file_syntax(file_id); | 189 | let file = self.file_syntax(file_id); |
173 | libeditor::runnables(&file) | 190 | libeditor::runnables(&file) |
diff --git a/crates/libanalysis/src/module_map.rs b/crates/libanalysis/src/module_map.rs index 47c0018e1..38935807d 100644 --- a/crates/libanalysis/src/module_map.rs +++ b/crates/libanalysis/src/module_map.rs | |||
@@ -91,16 +91,38 @@ impl ModuleMap { | |||
91 | file_resolver: &FileResolver, | 91 | file_resolver: &FileResolver, |
92 | syntax_provider: &SyntaxProvider, | 92 | syntax_provider: &SyntaxProvider, |
93 | ) -> Vec<(ModuleId, SmolStr, SyntaxNode)> { | 93 | ) -> Vec<(ModuleId, SmolStr, SyntaxNode)> { |
94 | let links = self.links(file_resolver, syntax_provider); | 94 | let mut res = Vec::new(); |
95 | let res = links | 95 | self.for_each_parent_link(m, file_resolver, syntax_provider, |link| { |
96 | res.push( | ||
97 | (link.owner, link.name().clone(), link.syntax.clone()) | ||
98 | ) | ||
99 | }); | ||
100 | res | ||
101 | } | ||
102 | |||
103 | pub fn parent_module_ids( | ||
104 | &self, | ||
105 | m: ModuleId, | ||
106 | file_resolver: &FileResolver, | ||
107 | syntax_provider: &SyntaxProvider, | ||
108 | ) -> Vec<ModuleId> { | ||
109 | let mut res = Vec::new(); | ||
110 | self.for_each_parent_link(m, file_resolver, syntax_provider, |link| res.push(link.owner)); | ||
111 | res | ||
112 | } | ||
113 | |||
114 | fn for_each_parent_link( | ||
115 | &self, | ||
116 | m: ModuleId, | ||
117 | file_resolver: &FileResolver, | ||
118 | syntax_provider: &SyntaxProvider, | ||
119 | f: impl FnMut(&Link) | ||
120 | ) { | ||
121 | self.links(file_resolver, syntax_provider) | ||
96 | .links | 122 | .links |
97 | .iter() | 123 | .iter() |
98 | .filter(move |link| link.points_to.iter().any(|&it| it == m)) | 124 | .filter(move |link| link.points_to.iter().any(|&it| it == m)) |
99 | .map(|link| { | 125 | .for_each(f) |
100 | (link.owner, link.name().clone(), link.syntax.clone()) | ||
101 | }) | ||
102 | .collect(); | ||
103 | res | ||
104 | } | 126 | } |
105 | 127 | ||
106 | pub fn problems( | 128 | pub fn problems( |