From b7d5172f69204b6d097d80a39dacad3494a26f5e Mon Sep 17 00:00:00 2001 From: veetaha Date: Wed, 1 Apr 2020 02:15:20 +0300 Subject: Simpify workspace handling --- crates/ra_project_model/src/lib.rs | 46 ++++++++------------ crates/rust-analyzer/src/cli/analysis_bench.rs | 4 +- crates/rust-analyzer/src/cli/analysis_stats.rs | 2 +- crates/rust-analyzer/src/cli/load_cargo.rs | 22 ++++------ crates/rust-analyzer/src/main_loop.rs | 4 +- crates/rust-analyzer/src/vfs_glob.rs | 10 +++-- crates/rust-analyzer/src/world.rs | 58 +++++++++++--------------- 7 files changed, 63 insertions(+), 83 deletions(-) (limited to 'crates') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index dd9c80691..a133243b4 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -58,22 +58,16 @@ pub enum ProjectWorkspace { #[derive(Clone)] pub struct PackageRoot { /// Path to the root folder - path: PathBuf, + pub path: PathBuf, /// Is a member of the current workspace - is_member: bool, + pub is_member: bool, } - impl PackageRoot { - pub fn new(path: PathBuf, is_member: bool) -> PackageRoot { - PackageRoot { path, is_member } - } - - pub fn path(&self) -> &PathBuf { - &self.path + pub fn new_member(path: PathBuf) -> PackageRoot { + Self { path, is_member: true } } - - pub fn is_member(&self) -> bool { - self.is_member + pub fn new_non_member(path: PathBuf) -> PackageRoot { + Self { path, is_member: false } } } @@ -130,24 +124,18 @@ impl ProjectWorkspace { pub fn to_roots(&self) -> Vec { match self { ProjectWorkspace::Json { project } => { - let mut roots = Vec::with_capacity(project.roots.len()); - for root in &project.roots { - roots.push(PackageRoot::new(root.path.clone(), true)); - } - roots - } - ProjectWorkspace::Cargo { cargo, sysroot } => { - let mut roots = Vec::with_capacity(cargo.packages().len() + sysroot.crates().len()); - for pkg in cargo.packages() { - let root = cargo[pkg].root().to_path_buf(); - let member = cargo[pkg].is_member; - roots.push(PackageRoot::new(root, member)); - } - for krate in sysroot.crates() { - roots.push(PackageRoot::new(sysroot[krate].root_dir().to_path_buf(), false)) - } - roots + project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() } + ProjectWorkspace::Cargo { cargo, sysroot } => cargo + .packages() + .map(|pkg| PackageRoot { + path: cargo[pkg].root().to_path_buf(), + is_member: cargo[pkg].is_member, + }) + .chain(sysroot.crates().map(|krate| { + PackageRoot::new_non_member(sysroot[krate].root_dir().to_path_buf()) + })) + .collect(), } } diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs index 7667873d5..0b138edd7 100644 --- a/crates/rust-analyzer/src/cli/analysis_bench.rs +++ b/crates/rust-analyzer/src/cli/analysis_bench.rs @@ -65,10 +65,10 @@ pub fn analysis_bench( roots .iter() .find_map(|(source_root_id, project_root)| { - if project_root.is_member() { + if project_root.is_member { for file_id in db.source_root(*source_root_id).walk() { let rel_path = db.file_relative_path(file_id); - let abs_path = rel_path.to_path(project_root.path()); + let abs_path = rel_path.to_path(&project_root.path); if abs_path == path { return Some(file_id); } diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 75cf2dae5..edd90df77 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -39,7 +39,7 @@ pub fn analysis_stats( roots .into_iter() .filter_map(|(source_root_id, project_root)| { - if with_deps || project_root.is_member() { + if with_deps || project_root.is_member { Some(source_root_id) } else { None diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 2c0bde920..109b1d74b 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs @@ -36,8 +36,7 @@ pub(crate) fn load_cargo( extern_dirs.extend(ws.out_dirs()); let mut project_roots = ws.to_roots(); - project_roots - .extend(extern_dirs.iter().map(|path| PackageRoot::new(path.to_path_buf(), false))); + project_roots.extend(extern_dirs.iter().cloned().map(PackageRoot::new_non_member)); let (sender, receiver) = unbounded(); let sender = Box::new(move |t| sender.send(t).unwrap()); @@ -46,9 +45,9 @@ pub(crate) fn load_cargo( .iter() .map(|pkg_root| { RootEntry::new( - pkg_root.path().clone(), + pkg_root.path.clone(), RustPackageFilterBuilder::default() - .set_member(pkg_root.is_member()) + .set_member(pkg_root.is_member) .into_vfs_filter(), ) }) @@ -58,14 +57,11 @@ pub(crate) fn load_cargo( ); let source_roots = roots - .iter() - .map(|&vfs_root| { + .into_iter() + .map(|vfs_root| { let source_root_id = vfs_root_to_id(vfs_root); - let project_root = project_roots - .iter() - .find(|it| it.path() == &vfs.root2path(vfs_root)) - .unwrap() - .clone(); + let project_root = + project_roots.iter().find(|it| it.path == vfs.root2path(vfs_root)).unwrap().clone(); (source_root_id, project_root) }) .collect::>(); @@ -97,7 +93,7 @@ pub(crate) fn load( match change { VfsChange::AddRoot { root, files } => { let source_root_id = vfs_root_to_id(root); - let is_local = source_roots[&source_root_id].is_member(); + let is_local = source_roots[&source_root_id].is_member; log::debug!( "loaded source root {:?} with path {:?}", source_root_id, @@ -106,7 +102,7 @@ pub(crate) fn load( analysis_change.add_root(source_root_id, is_local); analysis_change.set_debug_root_path( source_root_id, - source_roots[&source_root_id].path().display().to_string(), + source_roots[&source_root_id].path.display().to_string(), ); let vfs_root_path = vfs.root2path(root); diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 95e676e0f..e61a56935 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -132,8 +132,8 @@ pub fn main_loop(ws_roots: Vec, config: Config, connection: Connection) watchers: workspaces .iter() .flat_map(|ws| ws.to_roots()) - .filter(|root| root.is_member()) - .map(|root| format!("{}/**/*.rs", root.path().display())) + .filter(|root| root.is_member) + .map(|root| format!("{}/**/*.rs", root.path.display())) .map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None }) .collect(), }; diff --git a/crates/rust-analyzer/src/vfs_glob.rs b/crates/rust-analyzer/src/vfs_glob.rs index 91b33f94e..ff37a7008 100644 --- a/crates/rust-analyzer/src/vfs_glob.rs +++ b/crates/rust-analyzer/src/vfs_glob.rs @@ -29,10 +29,14 @@ impl RustPackageFilterBuilder { self.is_member = is_member; self } - pub fn exclude(mut self, glob: Glob) -> RustPackageFilterBuilder { - self.exclude.add(glob); + + pub fn exclude(mut self, globs: impl IntoIterator) -> RustPackageFilterBuilder { + for glob in globs.into_iter() { + self.exclude.add(glob); + } self } + pub fn into_vfs_filter(self) -> Box { let RustPackageFilterBuilder { is_member, mut exclude } = self; for &glob in ALWAYS_IGNORED { @@ -87,7 +91,7 @@ fn test_globs() { let filter = RustPackageFilterBuilder::default() .set_member(true) - .exclude(Glob::new("src/llvm-project/**").unwrap()) + .exclude(std::iter::once(Glob::new("src/llvm-project/**").unwrap())) .into_vfs_filter(); assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang"))); diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index 5674f42ef..a6549a8f4 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs @@ -87,44 +87,35 @@ impl WorldState { ) -> WorldState { let mut change = AnalysisChange::new(); - let mut roots = Vec::new(); - roots.extend(folder_roots.iter().map(|path| { - let mut filter = RustPackageFilterBuilder::default().set_member(true); - for glob in exclude_globs.iter() { - filter = filter.exclude(glob.clone()); - } - RootEntry::new(path.clone(), filter.into_vfs_filter()) - })); - for ws in workspaces.iter() { - roots.extend(ws.to_roots().into_iter().map(|pkg_root| { - let mut filter = - RustPackageFilterBuilder::default().set_member(pkg_root.is_member()); - for glob in exclude_globs.iter() { - filter = filter.exclude(glob.clone()); - } - RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter()) - })); - } - - let mut extern_dirs = FxHashSet::default(); - for ws in workspaces.iter() { - extern_dirs.extend(ws.out_dirs()); - } - - let mut extern_source_roots = FxHashMap::default(); - - roots.extend(extern_dirs.iter().map(|path| { - let mut filter = RustPackageFilterBuilder::default().set_member(false); - for glob in exclude_globs.iter() { - filter = filter.exclude(glob.clone()); - } - RootEntry::new(PathBuf::from(&path), filter.into_vfs_filter()) - })); + let extern_dirs: FxHashSet<_> = + workspaces.iter().flat_map(ProjectWorkspace::out_dirs).collect(); + + let roots: Vec<_> = { + let create_filter = |is_member| { + RustPackageFilterBuilder::default() + .set_member(is_member) + .exclude(exclude_globs.iter().cloned()) + .into_vfs_filter() + }; + folder_roots + .iter() + .map(|path| RootEntry::new(path.clone(), create_filter(true))) + .chain(workspaces.iter().flat_map(ProjectWorkspace::to_roots).map(|pkg_root| { + RootEntry::new(pkg_root.path, create_filter(pkg_root.is_member)) + })) + .chain( + extern_dirs + .iter() + .map(|path| RootEntry::new(path.to_owned(), create_filter(false))), + ) + .collect() + }; let (task_sender, task_receiver) = unbounded(); let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); + let mut extern_source_roots = FxHashMap::default(); for r in vfs_roots { let vfs_root_path = vfs.root2path(r); let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); @@ -132,6 +123,7 @@ impl WorldState { change.set_debug_root_path(SourceRootId(r.0), vfs_root_path.display().to_string()); // FIXME: add path2root in vfs to simpily this logic + if extern_dirs.contains(&vfs_root_path) { extern_source_roots.insert(vfs_root_path, ExternSourceId(r.0)); } -- cgit v1.2.3