aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-15 18:29:22 +0100
committerAleksey Kladov <[email protected]>2018-09-15 22:00:05 +0100
commit58674dc3c415142dbdd93b990d9f5b4fe10bef69 (patch)
treed30f60432f96e256d20e805e1f62a3084f61644a /crates
parentd59413c895e7b49ed2ad01be35871e417a57a43c (diff)
ModuleTreeDescriptor
Diffstat (limited to 'crates')
-rw-r--r--crates/libanalysis/src/db/mod.rs12
-rw-r--r--crates/libanalysis/src/descriptors.rs217
-rw-r--r--crates/libanalysis/src/imp.rs124
-rw-r--r--crates/libanalysis/src/lib.rs1
-rw-r--r--crates/libanalysis/src/module_map_db/descr.rs29
-rw-r--r--crates/libanalysis/src/module_map_db/mod.rs47
-rw-r--r--crates/libanalysis/src/roots.rs12
-rw-r--r--crates/libeditor/src/line_index.rs2
8 files changed, 306 insertions, 138 deletions
diff --git a/crates/libanalysis/src/db/mod.rs b/crates/libanalysis/src/db/mod.rs
index a775b5f75..1111a4f87 100644
--- a/crates/libanalysis/src/db/mod.rs
+++ b/crates/libanalysis/src/db/mod.rs
@@ -68,22 +68,32 @@ pub(crate) fn file_set(ctx: QueryCtx) -> Arc<(Vec<FileId>, FileResolverImp)> {
68pub(crate) use self::queries::file_syntax; 68pub(crate) use self::queries::file_syntax;
69 69
70mod queries { 70mod queries {
71 use std::sync::Arc;
71 use libsyntax2::File; 72 use libsyntax2::File;
73 use libeditor::LineIndex;
72 use {FileId}; 74 use {FileId};
73 use super::{Query, QueryCtx, QueryRegistry, file_text}; 75 use super::{Query, QueryCtx, QueryRegistry, file_text};
74 76
75 pub(crate) fn register_queries(reg: &mut QueryRegistry) { 77 pub(crate) fn register_queries(reg: &mut QueryRegistry) {
76 reg.add(FILE_SYNTAX, "FILE_SYNTAX") 78 reg.add(FILE_SYNTAX, "FILE_SYNTAX");
79 reg.add(FILE_LINES, "FILE_LINES");
77 } 80 }
78 81
79 pub(crate) fn file_syntax(ctx: QueryCtx, file_id: FileId) -> File { 82 pub(crate) fn file_syntax(ctx: QueryCtx, file_id: FileId) -> File {
80 (&*ctx.get(FILE_SYNTAX, file_id)).clone() 83 (&*ctx.get(FILE_SYNTAX, file_id)).clone()
81 } 84 }
85 pub(crate) fn file_lines(ctx: QueryCtx, file_id: FileId) -> Arc<LineIndex> {
86 ctx.get(FILE_LINES, file_id)
87 }
82 88
83 pub(super) const FILE_SYNTAX: Query<FileId, File> = Query(16, |ctx, file_id: &FileId| { 89 pub(super) const FILE_SYNTAX: Query<FileId, File> = Query(16, |ctx, file_id: &FileId| {
84 let text = file_text(ctx, *file_id); 90 let text = file_text(ctx, *file_id);
85 File::parse(&*text) 91 File::parse(&*text)
86 }); 92 });
93 pub(super) const FILE_LINES: Query<FileId, LineIndex> = Query(17, |ctx, file_id: &FileId| {
94 let text = file_text(ctx, *file_id);
95 LineIndex::new(&*text)
96 });
87} 97}
88 98
89impl QueryRegistry { 99impl QueryRegistry {
diff --git a/crates/libanalysis/src/descriptors.rs b/crates/libanalysis/src/descriptors.rs
new file mode 100644
index 000000000..e21ee728f
--- /dev/null
+++ b/crates/libanalysis/src/descriptors.rs
@@ -0,0 +1,217 @@
1use std::{
2 collections::BTreeMap,
3};
4use relative_path::RelativePathBuf;
5use libsyntax2::{
6 SmolStr,
7 ast::{self, NameOwner},
8};
9use {
10 FileId,
11 imp::FileResolverImp,
12};
13
14#[derive(Debug, Hash)]
15pub struct ModuleDescriptor {
16 pub submodules: Vec<Submodule>
17}
18
19impl ModuleDescriptor {
20 pub fn new(root: ast::Root) -> ModuleDescriptor {
21 let submodules = modules(root)
22 .map(|(name, _)| Submodule { name })
23 .collect();
24
25 ModuleDescriptor { submodules } }
26}
27
28fn modules<'a>(root: ast::Root<'a>) -> impl Iterator<Item=(SmolStr, ast::Module<'a>)> {
29 root
30 .modules()
31 .filter_map(|module| {
32 let name = module.name()?.text();
33 if !module.has_semi() {
34 return None;
35 }
36 Some((name, module))
37 })
38}
39
40#[derive(Clone, Hash, PartialEq, Eq, Debug)]
41pub struct Submodule {
42 pub name: SmolStr,
43}
44
45#[derive(Hash)]
46pub(crate) struct ModuleTreeDescriptor {
47 nodes: Vec<NodeData>,
48 links: Vec<LinkData>,
49 file_id2node: BTreeMap<FileId, Node>,
50}
51
52#[derive(Clone, Copy, PartialEq, Eq, Hash)]
53struct Node(usize);
54#[derive(Hash)]
55struct NodeData {
56 file_id: FileId,
57 links: Vec<Link>,
58 parents: Vec<Link>
59}
60
61#[derive(Clone, Copy, PartialEq, Eq, Hash)]
62pub(crate) struct Link(usize);
63#[derive(Hash)]
64struct LinkData {
65 owner: Node,
66 name: SmolStr,
67 points_to: Vec<Node>,
68 problem: Option<Problem>,
69}
70
71
72#[derive(Clone, Debug, Hash)]
73pub enum Problem {
74 UnresolvedModule {
75 candidate: RelativePathBuf,
76 },
77 NotDirOwner {
78 move_to: RelativePathBuf,
79 candidate: RelativePathBuf,
80 }
81}
82
83impl ModuleTreeDescriptor {
84 pub(crate) fn new<'a>(
85 files: impl Iterator<Item=(FileId, &'a ModuleDescriptor)> + Clone,
86 file_resolver: &FileResolverImp,
87 ) -> ModuleTreeDescriptor {
88 let mut file_id2node = BTreeMap::new();
89 let mut nodes: Vec<NodeData> = files.clone().enumerate()
90 .map(|(idx, (file_id, _))| {
91 file_id2node.insert(file_id, Node(idx));
92 NodeData {
93 file_id,
94 links: Vec::new(),
95 parents: Vec::new(),
96 }
97 })
98 .collect();
99 let mut links = Vec::new();
100
101 for (idx, (file_id, descr)) in files.enumerate() {
102 let owner = Node(idx);
103 for sub in descr.submodules.iter() {
104 let link = Link(links.len());
105 nodes[owner.0].links.push(link);
106 let (points_to, problem) = resolve_submodule(file_id, &sub.name, file_resolver);
107 let points_to = points_to
108 .into_iter()
109 .map(|file_id| {
110 let node = file_id2node[&file_id];
111 nodes[node.0].parents.push(link);
112 node
113 })
114 .collect();
115
116 links.push(LinkData {
117 owner,
118 name: sub.name.clone(),
119 points_to,
120 problem,
121 })
122
123 }
124 }
125
126 ModuleTreeDescriptor {
127 nodes, links, file_id2node
128 }
129 }
130
131 pub(crate) fn parent_modules(&self, file_id: FileId) -> Vec<Link> {
132 let node = self.file_id2node[&file_id];
133 self.node(node)
134 .parents
135 .clone()
136 }
137 pub(crate) fn child_module_by_name(&self, file_id: FileId, name: &str) -> Vec<FileId> {
138 let node = self.file_id2node[&file_id];
139 self.node(node)
140 .links
141 .iter()
142 .filter(|it| it.name(self) == name)
143 .map(|link| link.owner(self))
144 .collect()
145 }
146 pub(crate) fn problems<'a, 'b>(&'b self, file_id: FileId, root: ast::Root<'a>) -> Vec<(ast::Name<'a>, &'b Problem)> {
147 let node = self.file_id2node[&file_id];
148 self.node(node)
149 .links
150 .iter()
151 .filter_map(|&link| {
152 let problem = self.link(link).problem.as_ref()?;
153 let name = link.bind_source(self, root).name()?;
154 Some((name, problem))
155 })
156 .collect()
157 }
158
159 fn node(&self, node: Node) -> &NodeData {
160 &self.nodes[node.0]
161 }
162 fn link(&self, link: Link) -> &LinkData {
163 &self.links[link.0]
164 }
165}
166
167impl Link {
168 pub(crate) fn name(self, tree: &ModuleTreeDescriptor) -> SmolStr {
169 tree.link(self).name.clone()
170 }
171 pub(crate) fn owner(self, tree: &ModuleTreeDescriptor) -> FileId {
172 let owner = tree.link(self).owner;
173 tree.node(owner).file_id
174 }
175 pub(crate) fn bind_source<'a>(self, tree: &ModuleTreeDescriptor, root: ast::Root<'a>) -> ast::Module<'a> {
176 modules(root)
177 .filter(|(name, _)| name == &tree.link(self).name)
178 .next()
179 .unwrap()
180 .1
181 }
182}
183
184
185fn resolve_submodule(
186 file_id: FileId,
187 name: &SmolStr,
188 file_resolver: &FileResolverImp
189) -> (Vec<FileId>, Option<Problem>) {
190 let mod_name = file_resolver.file_stem(file_id);
191 let is_dir_owner =
192 mod_name == "mod" || mod_name == "lib" || mod_name == "main";
193
194 let file_mod = RelativePathBuf::from(format!("../{}.rs", name));
195 let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name));
196 let points_to: Vec<FileId>;
197 let problem: Option<Problem>;
198 if is_dir_owner {
199 points_to = [&file_mod, &dir_mod].iter()
200 .filter_map(|path| file_resolver.resolve(file_id, path))
201 .collect();
202 problem = if points_to.is_empty() {
203 Some(Problem::UnresolvedModule {
204 candidate: file_mod,
205 })
206 } else {
207 None
208 }
209 } else {
210 points_to = Vec::new();
211 problem = Some(Problem::NotDirOwner {
212 move_to: RelativePathBuf::from(format!("../{}/mod.rs", mod_name)),
213 candidate: file_mod,
214 });
215 }
216 (points_to, problem)
217}
diff --git a/crates/libanalysis/src/imp.rs b/crates/libanalysis/src/imp.rs
index 3e65ee14a..8734813f4 100644
--- a/crates/libanalysis/src/imp.rs
+++ b/crates/libanalysis/src/imp.rs
@@ -18,8 +18,8 @@ use libsyntax2::{
18use { 18use {
19 FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit, 19 FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit,
20 JobToken, CrateGraph, CrateId, 20 JobToken, CrateGraph, CrateId,
21 module_map::{ModuleMap, Problem},
22 roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot}, 21 roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot},
22 descriptors::{ModuleTreeDescriptor, Problem},
23}; 23};
24 24
25 25
@@ -148,25 +148,24 @@ impl AnalysisImpl {
148 } 148 }
149 pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { 149 pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> {
150 let root = self.root(file_id); 150 let root = self.root(file_id);
151 let module_map = root.module_map(); 151 let module_tree = root.module_tree();
152 let id = module_map.file2module(file_id); 152 module_tree.parent_modules(file_id)
153 module_map 153 .iter()
154 .parent_modules(id, &|file_id| root.syntax(file_id)) 154 .map(|link| {
155 .into_iter() 155 let file_id = link.owner(&module_tree);
156 .map(|(id, name, node)| { 156 let syntax = root.syntax(file_id);
157 let id = module_map.module2file(id); 157 let decl = link.bind_source(&module_tree, syntax.ast());
158 let sym = FileSymbol { 158 let sym = FileSymbol {
159 name, 159 name: link.name(&module_tree),
160 node_range: node.range(), 160 node_range: decl.syntax().range(),
161 kind: MODULE, 161 kind: MODULE,
162 }; 162 };
163 (id, sym) 163 (file_id, sym)
164 }) 164 })
165 .collect() 165 .collect()
166 } 166 }
167
168 pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> { 167 pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> {
169 let module_map = self.root(file_id).module_map(); 168 let module_tree = self.root(file_id).module_tree();
170 let crate_graph = &self.data.crate_graph; 169 let crate_graph = &self.data.crate_graph;
171 let mut res = Vec::new(); 170 let mut res = Vec::new();
172 let mut work = VecDeque::new(); 171 let mut work = VecDeque::new();
@@ -177,11 +176,10 @@ impl AnalysisImpl {
177 res.push(crate_id); 176 res.push(crate_id);
178 continue; 177 continue;
179 } 178 }
180 let mid = module_map.file2module(id); 179 let parents = module_tree
181 let parents = module_map 180 .parent_modules(id)
182 .parent_module_ids(mid, &|file_id| self.file_syntax(file_id))
183 .into_iter() 181 .into_iter()
184 .map(|id| module_map.module2file(id)) 182 .map(|link| link.owner(&module_tree))
185 .filter(|&id| visited.insert(id)); 183 .filter(|&id| visited.insert(id));
186 work.extend(parents); 184 work.extend(parents);
187 } 185 }
@@ -197,7 +195,7 @@ impl AnalysisImpl {
197 token: &JobToken, 195 token: &JobToken,
198 ) -> Vec<(FileId, FileSymbol)> { 196 ) -> Vec<(FileId, FileSymbol)> {
199 let root = self.root(file_id); 197 let root = self.root(file_id);
200 let module_map = root.module_map(); 198 let module_tree = root.module_tree();
201 let file = root.syntax(file_id); 199 let file = root.syntax(file_id);
202 let syntax = file.syntax(); 200 let syntax = file.syntax();
203 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { 201 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
@@ -206,7 +204,7 @@ impl AnalysisImpl {
206 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, offset) { 204 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, offset) {
207 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { 205 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
208 if module.has_semi() { 206 if module.has_semi() {
209 let file_ids = self.resolve_module(module_map, file_id, module); 207 let file_ids = self.resolve_module(&*module_tree, file_id, module);
210 208
211 let res = file_ids.into_iter().map(|id| { 209 let res = file_ids.into_iter().map(|id| {
212 let name = module.name() 210 let name = module.name()
@@ -229,7 +227,7 @@ impl AnalysisImpl {
229 227
230 pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> { 228 pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
231 let root = self.root(file_id); 229 let root = self.root(file_id);
232 let module_map = root.module_map(); 230 let module_tree = root.module_tree();
233 let syntax = root.syntax(file_id); 231 let syntax = root.syntax(file_id);
234 232
235 let mut res = libeditor::diagnostics(&syntax) 233 let mut res = libeditor::diagnostics(&syntax)
@@ -237,47 +235,43 @@ impl AnalysisImpl {
237 .map(|d| Diagnostic { range: d.range, message: d.msg, fix: None }) 235 .map(|d| Diagnostic { range: d.range, message: d.msg, fix: None })
238 .collect::<Vec<_>>(); 236 .collect::<Vec<_>>();
239 237
240 module_map.problems( 238 for (name_node, problem) in module_tree.problems(file_id, syntax.ast()) {
241 file_id, 239 let diag = match problem {
242 &|file_id| self.file_syntax(file_id), 240 Problem::UnresolvedModule { candidate } => {
243 |name_node, problem| { 241 let create_file = FileSystemEdit::CreateFile {
244 let diag = match problem { 242 anchor: file_id,
245 Problem::UnresolvedModule { candidate } => { 243 path: candidate.clone(),
246 let create_file = FileSystemEdit::CreateFile { 244 };
247 anchor: file_id, 245 let fix = SourceChange {
248 path: candidate.clone(), 246 label: "create module".to_string(),
249 }; 247 source_file_edits: Vec::new(),
250 let fix = SourceChange { 248 file_system_edits: vec![create_file],
251 label: "create module".to_string(), 249 cursor_position: None,
252 source_file_edits: Vec::new(), 250 };
253 file_system_edits: vec![create_file], 251 Diagnostic {
254 cursor_position: None, 252 range: name_node.syntax().range(),
255 }; 253 message: "unresolved module".to_string(),
256 Diagnostic { 254 fix: Some(fix),
257 range: name_node.syntax().range(),
258 message: "unresolved module".to_string(),
259 fix: Some(fix),
260 }
261 } 255 }
262 Problem::NotDirOwner { move_to, candidate } => { 256 }
263 let move_file = FileSystemEdit::MoveFile { file: file_id, path: move_to.clone() }; 257 Problem::NotDirOwner { move_to, candidate } => {
264 let create_file = FileSystemEdit::CreateFile { anchor: file_id, path: move_to.join(candidate) }; 258 let move_file = FileSystemEdit::MoveFile { file: file_id, path: move_to.clone() };
265 let fix = SourceChange { 259 let create_file = FileSystemEdit::CreateFile { anchor: file_id, path: move_to.join(candidate) };
266 label: "move file and create module".to_string(), 260 let fix = SourceChange {
267 source_file_edits: Vec::new(), 261 label: "move file and create module".to_string(),
268 file_system_edits: vec![move_file, create_file], 262 source_file_edits: Vec::new(),
269 cursor_position: None, 263 file_system_edits: vec![move_file, create_file],
270 }; 264 cursor_position: None,
271 Diagnostic { 265 };
272 range: name_node.syntax().range(), 266 Diagnostic {
273 message: "can't declare module at this location".to_string(), 267 range: name_node.syntax().range(),
274 fix: Some(fix), 268 message: "can't declare module at this location".to_string(),
275 } 269 fix: Some(fix),
276 } 270 }
277 }; 271 }
278 res.push(diag) 272 };
279 } 273 res.push(diag)
280 ); 274 }
281 res 275 res
282 } 276 }
283 277
@@ -307,20 +301,12 @@ impl AnalysisImpl {
307 self.world_symbols(query, token) 301 self.world_symbols(query, token)
308 } 302 }
309 303
310 fn resolve_module(&self, module_map: &ModuleMap, file_id: FileId, module: ast::Module) -> Vec<FileId> { 304 fn resolve_module(&self, module_tree: &ModuleTreeDescriptor, file_id: FileId, module: ast::Module) -> Vec<FileId> {
311 let name = match module.name() { 305 let name = match module.name() {
312 Some(name) => name.text(), 306 Some(name) => name.text(),
313 None => return Vec::new(), 307 None => return Vec::new(),
314 }; 308 };
315 let id = module_map.file2module(file_id); 309 module_tree.child_module_by_name(file_id, name.as_str())
316 module_map
317 .child_module_by_name(
318 id, name.as_str(),
319 &|file_id| self.file_syntax(file_id),
320 )
321 .into_iter()
322 .map(|id| module_map.module2file(id))
323 .collect()
324 } 310 }
325 311
326 fn reindex(&self) { 312 fn reindex(&self) {
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index bca5d4c1d..ea3a28702 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -19,6 +19,7 @@ mod imp;
19mod job; 19mod job;
20mod roots; 20mod roots;
21mod db; 21mod db;
22mod descriptors;
22 23
23use std::{ 24use std::{
24 sync::Arc, 25 sync::Arc,
diff --git a/crates/libanalysis/src/module_map_db/descr.rs b/crates/libanalysis/src/module_map_db/descr.rs
deleted file mode 100644
index fb298a315..000000000
--- a/crates/libanalysis/src/module_map_db/descr.rs
+++ /dev/null
@@ -1,29 +0,0 @@
1use libsyntax2::{
2 SmolStr,
3 ast::{self, NameOwner},
4};
5
6#[derive(Debug, Hash)]
7pub struct ModuleDescr {
8 pub submodules: Vec<Submodule>
9}
10
11impl ModuleDescr {
12 pub fn new(root: ast::Root) -> ModuleDescr {
13 let submodules = root
14 .modules()
15 .filter_map(|module| {
16 let name = module.name()?.text();
17 if !module.has_semi() {
18 return None;
19 }
20 Some(Submodule { name })
21 }).collect();
22
23 ModuleDescr { submodules } }
24}
25
26#[derive(Clone, Hash, PartialEq, Eq, Debug)]
27pub struct Submodule {
28 pub name: SmolStr,
29}
diff --git a/crates/libanalysis/src/module_map_db/mod.rs b/crates/libanalysis/src/module_map_db/mod.rs
index 5560e4a34..adad943da 100644
--- a/crates/libanalysis/src/module_map_db/mod.rs
+++ b/crates/libanalysis/src/module_map_db/mod.rs
@@ -1,5 +1,3 @@
1mod descr;
2
3use std::sync::Arc; 1use std::sync::Arc;
4use { 2use {
5 FileId, 3 FileId,
@@ -7,49 +5,36 @@ use {
7 Query, QueryRegistry, QueryCtx, 5 Query, QueryRegistry, QueryCtx,
8 file_syntax, file_set 6 file_syntax, file_set
9 }, 7 },
10 module_map::resolve_submodule, 8 descriptors::{ModuleDescriptor, ModuleTreeDescriptor}
11}; 9};
12 10
13pub(crate) fn register_queries(reg: &mut QueryRegistry) { 11pub(crate) fn register_queries(reg: &mut QueryRegistry) {
14 reg.add(MODULE_DESCR, "MODULE_DESCR"); 12 reg.add(MODULE_DESCR, "MODULE_DESCR");
15 reg.add(RESOLVE_SUBMODULE, "RESOLVE_SUBMODULE"); 13}
16 reg.add(PARENT_MODULE, "PARENT_MODULE"); 14
15pub(crate) fn module_tree(ctx: QueryCtx) -> Arc<ModuleTreeDescriptor> {
16 ctx.get(MODULE_TREE, ())
17} 17}
18 18
19impl<'a> QueryCtx<'a> { 19impl<'a> QueryCtx<'a> {
20 fn module_descr(&self, file_id: FileId) -> Arc<descr::ModuleDescr> { 20 fn module_descr(&self, file_id: FileId) -> Arc<ModuleDescriptor> {
21 self.get(MODULE_DESCR, file_id) 21 self.get(MODULE_DESCR, file_id)
22 } 22 }
23 fn resolve_submodule(&self, file_id: FileId, submod: descr::Submodule) -> Arc<Vec<FileId>> {
24 self.get(RESOLVE_SUBMODULE, (file_id, submod))
25 }
26} 23}
27 24
28const MODULE_DESCR: Query<FileId, descr::ModuleDescr> = Query(30, |ctx, &file_id| { 25const MODULE_DESCR: Query<FileId, ModuleDescriptor> = Query(30, |ctx, &file_id| {
29 let file = file_syntax(ctx, file_id); 26 let file = file_syntax(ctx, file_id);
30 descr::ModuleDescr::new(file.ast()) 27 ModuleDescriptor::new(file.ast())
31}); 28});
32 29
33const RESOLVE_SUBMODULE: Query<(FileId, descr::Submodule), Vec<FileId>> = Query(31, |ctx, params| { 30const MODULE_TREE: Query<(), ModuleTreeDescriptor> = Query(31, |ctx, _| {
34 let files = file_set(ctx); 31 let file_set = file_set(ctx);
35 resolve_submodule(params.0, &params.1.name, &files.1).0 32 let mut files = Vec::new();
36}); 33 for &file_id in file_set.0.iter() {
37 34 let module_descr = ctx.get(MODULE_DESCR, file_id);
38const PARENT_MODULE: Query<FileId, Vec<FileId>> = Query(40, |ctx, file_id| { 35 files.push((file_id, module_descr));
39 let files = file_set(ctx); 36 }
40 let res = files.0.iter() 37 ModuleTreeDescriptor::new(files.iter().map(|(file_id, descr)| (*file_id, &**descr)), &file_set.1)
41 .map(|&parent_id| (parent_id, ctx.module_descr(parent_id)))
42 .filter(|(parent_id, descr)| {
43 descr.submodules.iter()
44 .any(|subm| {
45 ctx.resolve_submodule(*parent_id, subm.clone())
46 .iter()
47 .any(|it| it == file_id)
48 })
49 })
50 .map(|(id, _)| id)
51 .collect();
52 res
53}); 38});
54 39
55#[cfg(test)] 40#[cfg(test)]
diff --git a/crates/libanalysis/src/roots.rs b/crates/libanalysis/src/roots.rs
index 629a697c5..b925fd24d 100644
--- a/crates/libanalysis/src/roots.rs
+++ b/crates/libanalysis/src/roots.rs
@@ -15,11 +15,15 @@ use {
15 imp::FileResolverImp, 15 imp::FileResolverImp,
16 module_map::{ModuleMap, ChangeKind}, 16 module_map::{ModuleMap, ChangeKind},
17 symbol_index::SymbolIndex, 17 symbol_index::SymbolIndex,
18 descriptors::ModuleTreeDescriptor,
18}; 19};
19 20
20pub(crate) trait SourceRoot { 21pub(crate) trait SourceRoot {
21 fn contains(&self, file_id: FileId) -> bool; 22 fn contains(&self, file_id: FileId) -> bool;
22 fn module_map(&self) -> &ModuleMap; 23 fn module_tree(&self) -> Arc<ModuleTreeDescriptor> {
24 unimplemented!()
25 }
26 // fn module_map(&self) -> &ModuleMap;
23 fn lines(&self, file_id: FileId) -> &LineIndex; 27 fn lines(&self, file_id: FileId) -> &LineIndex;
24 fn syntax(&self, file_id: FileId) -> &File; 28 fn syntax(&self, file_id: FileId) -> &File;
25 fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>); 29 fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>);
@@ -74,9 +78,6 @@ impl SourceRoot for WritableSourceRoot {
74 fn contains(&self, file_id: FileId) -> bool { 78 fn contains(&self, file_id: FileId) -> bool {
75 self.file_map.contains_key(&file_id) 79 self.file_map.contains_key(&file_id)
76 } 80 }
77 fn module_map(&self) -> &ModuleMap {
78 &self.module_map
79 }
80 fn lines(&self, file_id: FileId) -> &LineIndex { 81 fn lines(&self, file_id: FileId) -> &LineIndex {
81 self.data(file_id).lines() 82 self.data(file_id).lines()
82 } 83 }
@@ -175,9 +176,6 @@ impl SourceRoot for ReadonlySourceRoot {
175 fn contains(&self, file_id: FileId) -> bool { 176 fn contains(&self, file_id: FileId) -> bool {
176 self.file_map.contains_key(&file_id) 177 self.file_map.contains_key(&file_id)
177 } 178 }
178 fn module_map(&self) -> &ModuleMap {
179 &self.module_map
180 }
181 fn lines(&self, file_id: FileId) -> &LineIndex { 179 fn lines(&self, file_id: FileId) -> &LineIndex {
182 self.data(file_id).lines() 180 self.data(file_id).lines()
183 } 181 }
diff --git a/crates/libeditor/src/line_index.rs b/crates/libeditor/src/line_index.rs
index 801726aa5..9cd8da3a8 100644
--- a/crates/libeditor/src/line_index.rs
+++ b/crates/libeditor/src/line_index.rs
@@ -1,7 +1,7 @@
1use superslice::Ext; 1use superslice::Ext;
2use ::TextUnit; 2use ::TextUnit;
3 3
4#[derive(Clone, Debug)] 4#[derive(Clone, Debug, Hash)]
5pub struct LineIndex { 5pub struct LineIndex {
6 newlines: Vec<TextUnit>, 6 newlines: Vec<TextUnit>,
7} 7}