aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/module_map.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis/src/module_map.rs')
-rw-r--r--crates/libanalysis/src/module_map.rs80
1 files changed, 62 insertions, 18 deletions
diff --git a/crates/libanalysis/src/module_map.rs b/crates/libanalysis/src/module_map.rs
index 4f480591e..b65569c46 100644
--- a/crates/libanalysis/src/module_map.rs
+++ b/crates/libanalysis/src/module_map.rs
@@ -1,6 +1,4 @@
1use std::{ 1use relative_path::RelativePathBuf;
2 path::{PathBuf},
3};
4 2
5use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; 3use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
6use libsyntax2::{ 4use libsyntax2::{
@@ -43,6 +41,18 @@ struct Link {
43 owner: ModuleId, 41 owner: ModuleId,
44 syntax: SyntaxNode, 42 syntax: SyntaxNode,
45 points_to: Vec<ModuleId>, 43 points_to: Vec<ModuleId>,
44 problem: Option<Problem>,
45}
46
47#[derive(Clone, Debug)]
48pub enum Problem {
49 UnresolvedModule {
50 candidate: RelativePathBuf,
51 },
52 NotDirOwner {
53 move_to: RelativePathBuf,
54 candidate: RelativePathBuf,
55 }
46} 56}
47 57
48impl ModuleMap { 58impl ModuleMap {
@@ -93,9 +103,24 @@ impl ModuleMap {
93 res 103 res
94 } 104 }
95 105
96 pub fn suggested_child_mod_path(&self, m: ast::Module) -> Option<PathBuf> { 106 pub fn problems(
97 let name = m.name()?; 107 &self,
98 Some(PathBuf::from(format!("../{}.rs", name.text()))) 108 file: FileId,
109 file_resolver: &FileResolver,
110 syntax_provider: &SyntaxProvider,
111 mut cb: impl FnMut(ast::Name, &Problem),
112 ) {
113 let module = self.file2module(file);
114 let links = self.links(file_resolver, syntax_provider);
115 links
116 .links
117 .iter()
118 .filter(|link| link.owner == module)
119 .filter_map(|link| {
120 let problem = link.problem.as_ref()?;
121 Some((link, problem))
122 })
123 .for_each(|(link, problem)| cb(link.name_node(), problem))
99 } 124 }
100 125
101 fn links( 126 fn links(
@@ -176,14 +201,17 @@ impl Link {
176 owner, 201 owner,
177 syntax: module.syntax().owned(), 202 syntax: module.syntax().owned(),
178 points_to: Vec::new(), 203 points_to: Vec::new(),
204 problem: None,
179 }; 205 };
180 Some(link) 206 Some(link)
181 } 207 }
182 208
183 fn name(&self) -> SmolStr { 209 fn name(&self) -> SmolStr {
184 self.ast().name() 210 self.name_node().text()
185 .unwrap() 211 }
186 .text() 212
213 fn name_node(&self) -> ast::Name {
214 self.ast().name().unwrap()
187 } 215 }
188 216
189 fn ast(&self) -> ast::Module { 217 fn ast(&self) -> ast::Module {
@@ -192,14 +220,30 @@ impl Link {
192 } 220 }
193 221
194 fn resolve(&mut self, file_resolver: &FileResolver) { 222 fn resolve(&mut self, file_resolver: &FileResolver) {
195 let name = self.name(); 223 let mod_name = file_resolver.file_stem(self.owner.0);
196 let paths = &[ 224 let is_dir_owner =
197 PathBuf::from(format!("../{}.rs", name)), 225 mod_name == "mod" || mod_name == "lib" || mod_name == "main";
198 PathBuf::from(format!("../{}/mod.rs", name)), 226
199 ]; 227 let file_mod = RelativePathBuf::from(format!("../{}.rs", self.name()));
200 self.points_to = paths.iter() 228 let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", self.name()));
201 .filter_map(|path| file_resolver(self.owner.0, path)) 229 if is_dir_owner {
202 .map(ModuleId) 230 self.points_to = [&file_mod, &dir_mod].iter()
203 .collect(); 231 .filter_map(|path| file_resolver.resolve(self.owner.0, path))
232 .map(ModuleId)
233 .collect();
234 self.problem = if self.points_to.is_empty() {
235 Some(Problem::UnresolvedModule {
236 candidate: file_mod,
237 })
238 } else {
239 None
240 }
241 } else {
242 self.points_to = Vec::new();
243 self.problem = Some(Problem::NotDirOwner {
244 move_to: RelativePathBuf::from(format!("../{}/mod.rs", mod_name)),
245 candidate: file_mod,
246 });
247 }
204 } 248 }
205} 249}