diff options
author | Aleksey Kladov <[email protected]> | 2018-09-15 18:29:22 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-09-15 22:00:05 +0100 |
commit | 58674dc3c415142dbdd93b990d9f5b4fe10bef69 (patch) | |
tree | d30f60432f96e256d20e805e1f62a3084f61644a | |
parent | d59413c895e7b49ed2ad01be35871e417a57a43c (diff) |
ModuleTreeDescriptor
-rw-r--r-- | crates/libanalysis/src/db/mod.rs | 12 | ||||
-rw-r--r-- | crates/libanalysis/src/descriptors.rs | 217 | ||||
-rw-r--r-- | crates/libanalysis/src/imp.rs | 124 | ||||
-rw-r--r-- | crates/libanalysis/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/libanalysis/src/module_map_db/descr.rs | 29 | ||||
-rw-r--r-- | crates/libanalysis/src/module_map_db/mod.rs | 47 | ||||
-rw-r--r-- | crates/libanalysis/src/roots.rs | 12 | ||||
-rw-r--r-- | crates/libeditor/src/line_index.rs | 2 |
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)> { | |||
68 | pub(crate) use self::queries::file_syntax; | 68 | pub(crate) use self::queries::file_syntax; |
69 | 69 | ||
70 | mod queries { | 70 | mod 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 | ||
89 | impl QueryRegistry { | 99 | impl 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 @@ | |||
1 | use std::{ | ||
2 | collections::BTreeMap, | ||
3 | }; | ||
4 | use relative_path::RelativePathBuf; | ||
5 | use libsyntax2::{ | ||
6 | SmolStr, | ||
7 | ast::{self, NameOwner}, | ||
8 | }; | ||
9 | use { | ||
10 | FileId, | ||
11 | imp::FileResolverImp, | ||
12 | }; | ||
13 | |||
14 | #[derive(Debug, Hash)] | ||
15 | pub struct ModuleDescriptor { | ||
16 | pub submodules: Vec<Submodule> | ||
17 | } | ||
18 | |||
19 | impl 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 | |||
28 | fn 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)] | ||
41 | pub struct Submodule { | ||
42 | pub name: SmolStr, | ||
43 | } | ||
44 | |||
45 | #[derive(Hash)] | ||
46 | pub(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)] | ||
53 | struct Node(usize); | ||
54 | #[derive(Hash)] | ||
55 | struct NodeData { | ||
56 | file_id: FileId, | ||
57 | links: Vec<Link>, | ||
58 | parents: Vec<Link> | ||
59 | } | ||
60 | |||
61 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | ||
62 | pub(crate) struct Link(usize); | ||
63 | #[derive(Hash)] | ||
64 | struct LinkData { | ||
65 | owner: Node, | ||
66 | name: SmolStr, | ||
67 | points_to: Vec<Node>, | ||
68 | problem: Option<Problem>, | ||
69 | } | ||
70 | |||
71 | |||
72 | #[derive(Clone, Debug, Hash)] | ||
73 | pub enum Problem { | ||
74 | UnresolvedModule { | ||
75 | candidate: RelativePathBuf, | ||
76 | }, | ||
77 | NotDirOwner { | ||
78 | move_to: RelativePathBuf, | ||
79 | candidate: RelativePathBuf, | ||
80 | } | ||
81 | } | ||
82 | |||
83 | impl 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 | |||
167 | impl 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 | |||
185 | fn 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::{ | |||
18 | use { | 18 | use { |
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; | |||
19 | mod job; | 19 | mod job; |
20 | mod roots; | 20 | mod roots; |
21 | mod db; | 21 | mod db; |
22 | mod descriptors; | ||
22 | 23 | ||
23 | use std::{ | 24 | use 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 @@ | |||
1 | use libsyntax2::{ | ||
2 | SmolStr, | ||
3 | ast::{self, NameOwner}, | ||
4 | }; | ||
5 | |||
6 | #[derive(Debug, Hash)] | ||
7 | pub struct ModuleDescr { | ||
8 | pub submodules: Vec<Submodule> | ||
9 | } | ||
10 | |||
11 | impl 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)] | ||
27 | pub 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 @@ | |||
1 | mod descr; | ||
2 | |||
3 | use std::sync::Arc; | 1 | use std::sync::Arc; |
4 | use { | 2 | use { |
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 | ||
13 | pub(crate) fn register_queries(reg: &mut QueryRegistry) { | 11 | pub(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 | |
15 | pub(crate) fn module_tree(ctx: QueryCtx) -> Arc<ModuleTreeDescriptor> { | ||
16 | ctx.get(MODULE_TREE, ()) | ||
17 | } | 17 | } |
18 | 18 | ||
19 | impl<'a> QueryCtx<'a> { | 19 | impl<'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 | ||
28 | const MODULE_DESCR: Query<FileId, descr::ModuleDescr> = Query(30, |ctx, &file_id| { | 25 | const 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 | ||
33 | const RESOLVE_SUBMODULE: Query<(FileId, descr::Submodule), Vec<FileId>> = Query(31, |ctx, params| { | 30 | const 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, ¶ms.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); | |
38 | const 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 | ||
20 | pub(crate) trait SourceRoot { | 21 | pub(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 @@ | |||
1 | use superslice::Ext; | 1 | use superslice::Ext; |
2 | use ::TextUnit; | 2 | use ::TextUnit; |
3 | 3 | ||
4 | #[derive(Clone, Debug)] | 4 | #[derive(Clone, Debug, Hash)] |
5 | pub struct LineIndex { | 5 | pub struct LineIndex { |
6 | newlines: Vec<TextUnit>, | 6 | newlines: Vec<TextUnit>, |
7 | } | 7 | } |