diff options
author | Aleksey Kladov <[email protected]> | 2018-10-23 17:15:31 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-10-23 18:44:23 +0100 |
commit | dc477db757247d5184250bffe9dd0c38dd867778 (patch) | |
tree | 1eebf0ff17462a44668f95b3e042de09d09985d0 /crates/ra_analysis/src/imp.rs | |
parent | 1d574ed6543936af7d1d16c4b4ea9b4bd858aa41 (diff) |
Introduce ModuleId
Previously, module was synonym with a file, and so a module could have
had several parents. This commit introduces a separate module concept,
such that each module has only one parent, but a single file can
correspond to different modules.
Diffstat (limited to 'crates/ra_analysis/src/imp.rs')
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 145 |
1 files changed, 73 insertions, 72 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 196627539..c15873328 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -1,5 +1,4 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | collections::VecDeque, | ||
3 | fmt, | 2 | fmt, |
4 | hash::{Hash, Hasher}, | 3 | hash::{Hash, Hasher}, |
5 | iter, | 4 | iter, |
@@ -17,7 +16,8 @@ use relative_path::RelativePath; | |||
17 | use rustc_hash::FxHashSet; | 16 | use rustc_hash::FxHashSet; |
18 | 17 | ||
19 | use crate::{ | 18 | use crate::{ |
20 | descriptors::{FnDescriptor, ModuleTreeDescriptor, Problem}, | 19 | descriptors::module::{ModuleTree, Problem}, |
20 | descriptors::{FnDescriptor}, | ||
21 | roots::{ReadonlySourceRoot, SourceRoot, WritableSourceRoot}, | 21 | roots::{ReadonlySourceRoot, SourceRoot, WritableSourceRoot}, |
22 | CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position, | 22 | CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position, |
23 | Query, SourceChange, SourceFileEdit, Cancelable, | 23 | Query, SourceChange, SourceFileEdit, Cancelable, |
@@ -113,7 +113,7 @@ impl AnalysisHostImpl { | |||
113 | self.data_mut().crate_graph = graph; | 113 | self.data_mut().crate_graph = graph; |
114 | } | 114 | } |
115 | pub fn add_library(&mut self, root: ReadonlySourceRoot) { | 115 | pub fn add_library(&mut self, root: ReadonlySourceRoot) { |
116 | self.data_mut().libs.push(Arc::new(root)); | 116 | self.data_mut().libs.push(root); |
117 | } | 117 | } |
118 | fn data_mut(&mut self) -> &mut WorldData { | 118 | fn data_mut(&mut self) -> &mut WorldData { |
119 | &mut self.data | 119 | &mut self.data |
@@ -135,7 +135,7 @@ impl AnalysisImpl { | |||
135 | if self.data.root.contains(file_id) { | 135 | if self.data.root.contains(file_id) { |
136 | return &self.data.root; | 136 | return &self.data.root; |
137 | } | 137 | } |
138 | &**self | 138 | self |
139 | .data | 139 | .data |
140 | .libs | 140 | .libs |
141 | .iter() | 141 | .iter() |
@@ -162,19 +162,21 @@ impl AnalysisImpl { | |||
162 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 162 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
163 | let root = self.root(file_id); | 163 | let root = self.root(file_id); |
164 | let module_tree = root.module_tree()?; | 164 | let module_tree = root.module_tree()?; |
165 | let res = module_tree | 165 | |
166 | .parent_modules(file_id) | 166 | let res = module_tree.modules_for_file(file_id) |
167 | .iter() | 167 | .into_iter() |
168 | .map(|link| { | 168 | .filter_map(|module_id| { |
169 | let file_id = link.owner(&module_tree); | 169 | let link = module_id.parent_link(&module_tree)?; |
170 | let file_id = link.owner(&module_tree).file_id(&module_tree); | ||
170 | let syntax = root.syntax(file_id); | 171 | let syntax = root.syntax(file_id); |
171 | let decl = link.bind_source(&module_tree, syntax.ast()); | 172 | let decl = link.bind_source(&module_tree, syntax.ast()); |
173 | |||
172 | let sym = FileSymbol { | 174 | let sym = FileSymbol { |
173 | name: link.name(&module_tree), | 175 | name: decl.name().unwrap().text(), |
174 | node_range: decl.syntax().range(), | 176 | node_range: decl.syntax().range(), |
175 | kind: MODULE, | 177 | kind: MODULE, |
176 | }; | 178 | }; |
177 | (file_id, sym) | 179 | Some((file_id, sym)) |
178 | }) | 180 | }) |
179 | .collect(); | 181 | .collect(); |
180 | Ok(res) | 182 | Ok(res) |
@@ -182,22 +184,13 @@ impl AnalysisImpl { | |||
182 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { | 184 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { |
183 | let module_tree = self.root(file_id).module_tree()?; | 185 | let module_tree = self.root(file_id).module_tree()?; |
184 | let crate_graph = &self.data.crate_graph; | 186 | let crate_graph = &self.data.crate_graph; |
185 | let mut res = Vec::new(); | 187 | let res = module_tree.modules_for_file(file_id) |
186 | let mut work = VecDeque::new(); | 188 | .into_iter() |
187 | work.push_back(file_id); | 189 | .map(|it| it.root(&module_tree)) |
188 | let mut visited = FxHashSet::default(); | 190 | .map(|it| it.file_id(&module_tree)) |
189 | while let Some(id) = work.pop_front() { | 191 | .filter_map(|it| crate_graph.crate_id_for_crate_root(it)) |
190 | if let Some(crate_id) = crate_graph.crate_id_for_crate_root(id) { | 192 | .collect(); |
191 | res.push(crate_id); | 193 | |
192 | continue; | ||
193 | } | ||
194 | let parents = module_tree | ||
195 | .parent_modules(id) | ||
196 | .into_iter() | ||
197 | .map(|link| link.owner(&module_tree)) | ||
198 | .filter(|&id| visited.insert(id)); | ||
199 | work.extend(parents); | ||
200 | } | ||
201 | Ok(res) | 194 | Ok(res) |
202 | } | 195 | } |
203 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { | 196 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { |
@@ -303,50 +296,51 @@ impl AnalysisImpl { | |||
303 | fix: None, | 296 | fix: None, |
304 | }) | 297 | }) |
305 | .collect::<Vec<_>>(); | 298 | .collect::<Vec<_>>(); |
306 | 299 | if let Some(m) = module_tree.any_module_for_file(file_id) { | |
307 | for (name_node, problem) in module_tree.problems(file_id, syntax.ast()) { | 300 | for (name_node, problem) in m.problems(&module_tree, syntax.ast()) { |
308 | let diag = match problem { | 301 | let diag = match problem { |
309 | Problem::UnresolvedModule { candidate } => { | 302 | Problem::UnresolvedModule { candidate } => { |
310 | let create_file = FileSystemEdit::CreateFile { | 303 | let create_file = FileSystemEdit::CreateFile { |
311 | anchor: file_id, | 304 | anchor: file_id, |
312 | path: candidate.clone(), | 305 | path: candidate.clone(), |
313 | }; | 306 | }; |
314 | let fix = SourceChange { | 307 | let fix = SourceChange { |
315 | label: "create module".to_string(), | 308 | label: "create module".to_string(), |
316 | source_file_edits: Vec::new(), | 309 | source_file_edits: Vec::new(), |
317 | file_system_edits: vec![create_file], | 310 | file_system_edits: vec![create_file], |
318 | cursor_position: None, | 311 | cursor_position: None, |
319 | }; | 312 | }; |
320 | Diagnostic { | 313 | Diagnostic { |
321 | range: name_node.syntax().range(), | 314 | range: name_node.range(), |
322 | message: "unresolved module".to_string(), | 315 | message: "unresolved module".to_string(), |
323 | fix: Some(fix), | 316 | fix: Some(fix), |
317 | } | ||
324 | } | 318 | } |
325 | } | 319 | Problem::NotDirOwner { move_to, candidate } => { |
326 | Problem::NotDirOwner { move_to, candidate } => { | 320 | let move_file = FileSystemEdit::MoveFile { |
327 | let move_file = FileSystemEdit::MoveFile { | 321 | file: file_id, |
328 | file: file_id, | 322 | path: move_to.clone(), |
329 | path: move_to.clone(), | 323 | }; |
330 | }; | 324 | let create_file = FileSystemEdit::CreateFile { |
331 | let create_file = FileSystemEdit::CreateFile { | 325 | anchor: file_id, |
332 | anchor: file_id, | 326 | path: move_to.join(candidate), |
333 | path: move_to.join(candidate), | 327 | }; |
334 | }; | 328 | let fix = SourceChange { |
335 | let fix = SourceChange { | 329 | label: "move file and create module".to_string(), |
336 | label: "move file and create module".to_string(), | 330 | source_file_edits: Vec::new(), |
337 | source_file_edits: Vec::new(), | 331 | file_system_edits: vec![move_file, create_file], |
338 | file_system_edits: vec![move_file, create_file], | 332 | cursor_position: None, |
339 | cursor_position: None, | 333 | }; |
340 | }; | 334 | Diagnostic { |
341 | Diagnostic { | 335 | range: name_node.range(), |
342 | range: name_node.syntax().range(), | 336 | message: "can't declare module at this location".to_string(), |
343 | message: "can't declare module at this location".to_string(), | 337 | fix: Some(fix), |
344 | fix: Some(fix), | 338 | } |
345 | } | 339 | } |
346 | } | 340 | }; |
347 | }; | 341 | res.push(diag) |
348 | res.push(diag) | 342 | } |
349 | } | 343 | }; |
350 | Ok(res) | 344 | Ok(res) |
351 | } | 345 | } |
352 | 346 | ||
@@ -457,7 +451,7 @@ impl AnalysisImpl { | |||
457 | 451 | ||
458 | fn resolve_module( | 452 | fn resolve_module( |
459 | &self, | 453 | &self, |
460 | module_tree: &ModuleTreeDescriptor, | 454 | module_tree: &ModuleTree, |
461 | file_id: FileId, | 455 | file_id: FileId, |
462 | module: ast::Module, | 456 | module: ast::Module, |
463 | ) -> Vec<FileId> { | 457 | ) -> Vec<FileId> { |
@@ -465,7 +459,14 @@ impl AnalysisImpl { | |||
465 | Some(name) => name.text(), | 459 | Some(name) => name.text(), |
466 | None => return Vec::new(), | 460 | None => return Vec::new(), |
467 | }; | 461 | }; |
468 | module_tree.child_module_by_name(file_id, name.as_str()) | 462 | let module_id = match module_tree.any_module_for_file(file_id) { |
463 | Some(id) => id, | ||
464 | None => return Vec::new(), | ||
465 | }; | ||
466 | module_id.child(module_tree, name.as_str()) | ||
467 | .map(|it| it.file_id(module_tree)) | ||
468 | .into_iter() | ||
469 | .collect() | ||
469 | } | 470 | } |
470 | } | 471 | } |
471 | 472 | ||
@@ -473,7 +474,7 @@ impl AnalysisImpl { | |||
473 | struct WorldData { | 474 | struct WorldData { |
474 | crate_graph: CrateGraph, | 475 | crate_graph: CrateGraph, |
475 | root: WritableSourceRoot, | 476 | root: WritableSourceRoot, |
476 | libs: Vec<Arc<ReadonlySourceRoot>>, | 477 | libs: Vec<ReadonlySourceRoot>, |
477 | } | 478 | } |
478 | 479 | ||
479 | impl SourceChange { | 480 | impl SourceChange { |