From d34588bf83898870d7f9b4b49ac2a5f71c77dabb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 28 Aug 2018 18:22:52 +0300 Subject: create module smartly --- crates/libanalysis/src/module_map.rs | 80 ++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 18 deletions(-) (limited to 'crates/libanalysis/src/module_map.rs') 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 @@ -use std::{ - path::{PathBuf}, -}; +use relative_path::RelativePathBuf; use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use libsyntax2::{ @@ -43,6 +41,18 @@ struct Link { owner: ModuleId, syntax: SyntaxNode, points_to: Vec, + problem: Option, +} + +#[derive(Clone, Debug)] +pub enum Problem { + UnresolvedModule { + candidate: RelativePathBuf, + }, + NotDirOwner { + move_to: RelativePathBuf, + candidate: RelativePathBuf, + } } impl ModuleMap { @@ -93,9 +103,24 @@ impl ModuleMap { res } - pub fn suggested_child_mod_path(&self, m: ast::Module) -> Option { - let name = m.name()?; - Some(PathBuf::from(format!("../{}.rs", name.text()))) + pub fn problems( + &self, + file: FileId, + file_resolver: &FileResolver, + syntax_provider: &SyntaxProvider, + mut cb: impl FnMut(ast::Name, &Problem), + ) { + let module = self.file2module(file); + let links = self.links(file_resolver, syntax_provider); + links + .links + .iter() + .filter(|link| link.owner == module) + .filter_map(|link| { + let problem = link.problem.as_ref()?; + Some((link, problem)) + }) + .for_each(|(link, problem)| cb(link.name_node(), problem)) } fn links( @@ -176,14 +201,17 @@ impl Link { owner, syntax: module.syntax().owned(), points_to: Vec::new(), + problem: None, }; Some(link) } fn name(&self) -> SmolStr { - self.ast().name() - .unwrap() - .text() + self.name_node().text() + } + + fn name_node(&self) -> ast::Name { + self.ast().name().unwrap() } fn ast(&self) -> ast::Module { @@ -192,14 +220,30 @@ impl Link { } fn resolve(&mut self, file_resolver: &FileResolver) { - let name = self.name(); - let paths = &[ - PathBuf::from(format!("../{}.rs", name)), - PathBuf::from(format!("../{}/mod.rs", name)), - ]; - self.points_to = paths.iter() - .filter_map(|path| file_resolver(self.owner.0, path)) - .map(ModuleId) - .collect(); + let mod_name = file_resolver.file_stem(self.owner.0); + let is_dir_owner = + mod_name == "mod" || mod_name == "lib" || mod_name == "main"; + + let file_mod = RelativePathBuf::from(format!("../{}.rs", self.name())); + let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", self.name())); + if is_dir_owner { + self.points_to = [&file_mod, &dir_mod].iter() + .filter_map(|path| file_resolver.resolve(self.owner.0, path)) + .map(ModuleId) + .collect(); + self.problem = if self.points_to.is_empty() { + Some(Problem::UnresolvedModule { + candidate: file_mod, + }) + } else { + None + } + } else { + self.points_to = Vec::new(); + self.problem = Some(Problem::NotDirOwner { + move_to: RelativePathBuf::from(format!("../{}/mod.rs", mod_name)), + candidate: file_mod, + }); + } } } -- cgit v1.2.3