#[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 }
}
}
pub fn to_roots(&self) -> Vec<PackageRoot> {
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(),
}
}
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);
}
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
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());
.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(),
)
})
);
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::<FxHashMap<_, _>>();
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,
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);
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(),
};
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<Item = Glob>) -> RustPackageFilterBuilder {
+ for glob in globs.into_iter() {
+ self.exclude.add(glob);
+ }
self
}
+
pub fn into_vfs_filter(self) -> Box<dyn Filter> {
let RustPackageFilterBuilder { is_member, mut exclude } = self;
for &glob in ALWAYS_IGNORED {
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")));
) -> 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));
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));
}